Line data Source code
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_SEGMENTS_ENCODED_REF_HPP
12 : #define BOOST_URL_SEGMENTS_ENCODED_REF_HPP
13 :
14 : #include <boost/url/detail/config.hpp>
15 : #include <boost/url/segments_encoded_base.hpp>
16 : #include <initializer_list>
17 : #include <iterator>
18 :
19 : namespace boost {
20 : namespace urls {
21 :
22 : #ifndef BOOST_URL_DOCS
23 : class url_base;
24 : class segments_encoded_view;
25 : #endif
26 :
27 : /** Mutable encoded path segment proxy
28 :
29 : Exposes the percent-encoded segments of a
30 : @ref url_base as a bidirectional range that
31 : can modify the underlying URL. The proxy uses
32 : the URL’s storage directly, so the url must
33 : outlive any references.
34 :
35 : @par Example
36 : @code
37 : url u( "/path/to/file.txt" );
38 :
39 : segments_encoded_ref ps = u.encoded_segments();
40 : @endcode
41 :
42 : The strings returned when iterators are
43 : dereferenced have type @ref pct_string_view
44 : and may contain percent-escapes.
45 :
46 : Reserved characters in inputs are
47 : automatically escaped.
48 : Escapes in inputs are preserved.
49 :
50 : Exceptions are thrown on invalid inputs.
51 :
52 : @par Iterator Invalidation
53 : Changes to the underlying character buffer
54 : can invalidate iterators which reference it.
55 : Modifications made through the container
56 : invalidate some or all iterators:
57 : <br>
58 :
59 : @li @ref push_back : Only `end()`.
60 :
61 : @li @ref assign, @ref clear,
62 : @ref operator= : All elements.
63 :
64 : @li @ref erase : Erased elements and all
65 : elements after (including `end()`).
66 :
67 : @li @ref insert : All elements at or after
68 : the insertion point (including `end()`).
69 :
70 : @li @ref replace : Modified
71 : elements and all elements
72 : after (including `end()`).
73 :
74 : @see
75 : @ref segments_encoded_view,
76 : @ref segments_view,
77 : @ref segments_ref.
78 : */
79 : class segments_encoded_ref
80 : : public segments_encoded_base
81 : {
82 : friend class url_base;
83 :
84 : url_base* u_ = nullptr;
85 :
86 : segments_encoded_ref(
87 : url_base& u) noexcept;
88 :
89 : public:
90 : //--------------------------------------------
91 : //
92 : // Special Members
93 : //
94 : //--------------------------------------------
95 :
96 : /** Constructor
97 :
98 : After construction, both views
99 : reference the same url. Ownership is not
100 : transferred; the caller is responsible
101 : for ensuring the lifetime of the url
102 : extends until it is no longer
103 : referenced.
104 :
105 : @par Postconditions
106 : @code
107 : &this->url() == &other.url();
108 : @endcode
109 :
110 : @par Complexity
111 : Constant.
112 :
113 : @par Exception Safety
114 : Throws nothing.
115 :
116 : @param other The other view.
117 : */
118 : segments_encoded_ref(
119 : segments_encoded_ref const& other) = default;
120 :
121 : /** Assignment
122 :
123 : The existing contents are replaced
124 : by a copy of the other segments.
125 :
126 : <br>
127 : All iterators are invalidated.
128 :
129 : @note
130 : None of the character buffers referenced
131 : by `other` may overlap the buffer of the
132 : underlying url, or else the behavior
133 : is undefined.
134 :
135 : @par Effects
136 : @code
137 : this->assign( other.begin(), other.end() );
138 : @endcode
139 :
140 : @par Complexity
141 : Linear in `other.buffer().size()`.
142 :
143 : @par Exception Safety
144 : Strong guarantee.
145 : Calls to allocate may throw.
146 :
147 : @param other The segments to assign.
148 : @return A reference to this object.
149 : */
150 : BOOST_URL_DECL
151 : segments_encoded_ref&
152 : operator=(segments_encoded_ref const& other);
153 :
154 : /// @copydoc operator=(segments_encoded_ref const&)
155 : BOOST_URL_DECL
156 : segments_encoded_ref&
157 : operator=(segments_encoded_view const& other);
158 :
159 : /** Assignment
160 :
161 : The existing contents are replaced
162 : by a copy of the contents of the
163 : initializer list.
164 : Reserved characters in the list are
165 : automatically escaped.
166 : Escapes in the list are preserved.
167 :
168 : <br>
169 : All iterators are invalidated.
170 :
171 : @par Example
172 : @code
173 : url u;
174 :
175 : u.encoded_segments() = {"path", "to", "file.txt"};
176 : @endcode
177 :
178 : @par Preconditions
179 : None of the character buffers referenced
180 : by the list may overlap the character buffer
181 : of the underlying url, or else the behavior
182 : is undefined.
183 :
184 : @par Effects
185 : @code
186 : this->assign( init.begin(), init.end() );
187 : @endcode
188 :
189 : @par Complexity
190 : Linear in `init.size() + this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
191 :
192 : @par Exception Safety
193 : Strong guarantee.
194 : Calls to allocate may throw.
195 : Exceptions thrown on invalid input.
196 :
197 : @throw system_error
198 : The list contains an invalid percent-encoding.
199 :
200 : @param init The list of segments to assign.
201 : @return A reference to this.
202 : */
203 : BOOST_URL_DECL
204 : segments_encoded_ref&
205 : operator=(std::initializer_list<
206 : pct_string_view> init);
207 :
208 : /** Conversion
209 :
210 : @see
211 : @ref segments_encoded_view.
212 :
213 : @return A view of the segments.
214 : */
215 : BOOST_URL_DECL
216 : operator
217 : segments_encoded_view() const noexcept;
218 :
219 : //--------------------------------------------
220 : //
221 : // Observers
222 : //
223 : //--------------------------------------------
224 :
225 : /** Return the referenced url
226 :
227 : This function returns the url referenced
228 : by the view.
229 :
230 : @par Example
231 : @code
232 : url u( "/path/to/file.txt" );
233 :
234 : assert( &u.encoded_segments().url() == &u );
235 : @endcode
236 :
237 : @par Exception Safety
238 : Throws nothing.
239 :
240 : @return A reference to the url.
241 : */
242 : url_base&
243 9 : url() const noexcept
244 : {
245 9 : return *u_;
246 : }
247 :
248 : //--------------------------------------------
249 : //
250 : // Modifiers
251 : //
252 : //--------------------------------------------
253 :
254 : /** Clear the contents of the container
255 :
256 : <br>
257 : All iterators are invalidated.
258 :
259 : @par Effects
260 : @code
261 : this->url().set_encoded_path( "" );
262 : @endcode
263 :
264 : @par Postconditions
265 : @code
266 : this->empty() == true
267 : @endcode
268 :
269 : @par Complexity
270 : Linear in `this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
271 :
272 : @par Exception Safety
273 : Throws nothing.
274 : */
275 : void
276 : clear() noexcept;
277 :
278 : /** Assign segments
279 :
280 : The existing contents are replaced
281 : by a copy of the contents of the
282 : initializer list.
283 : Reserved characters in the list are
284 : automatically escaped.
285 : Escapes in the list are preserved.
286 :
287 : <br>
288 : All iterators are invalidated.
289 :
290 : @note
291 : None of the character buffers referenced
292 : by the list may overlap the character
293 : buffer of the underlying url, or else
294 : the behavior is undefined.
295 :
296 : @par Example
297 : @code
298 : url u;
299 :
300 : u.segments().assign( {"path", "to", "file.txt"} );
301 : @endcode
302 :
303 : @par Complexity
304 : Linear in `init.size() + this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
305 :
306 : @par Exception Safety
307 : Strong guarantee.
308 : Calls to allocate may throw.
309 : Exceptions thrown on invalid input.
310 :
311 : @throw system_error
312 : The list contains an invalid percent-encoding.
313 :
314 : @param init The list of segments to assign.
315 : */
316 : BOOST_URL_DECL
317 : void
318 : assign(std::initializer_list<
319 : pct_string_view> init);
320 :
321 : /** Assign segments
322 :
323 : The existing contents are replaced
324 : by a copy of the contents of the range.
325 : Reserved characters in the range are
326 : automatically escaped.
327 : Escapes in the range are preserved.
328 :
329 : <br>
330 : All iterators are invalidated.
331 :
332 : @note
333 : None of the character buffers referenced
334 : by the range may overlap the character
335 : buffer of the underlying url, or else
336 : the behavior is undefined.
337 :
338 : @par Mandates
339 : @code
340 : std::is_convertible< std::iterator_traits< FwdIt >::reference_type, pct_string_view >::value == true
341 : @endcode
342 :
343 : @par Complexity
344 : Linear in `std::distance( first, last ) + this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
345 :
346 : @par Exception Safety
347 : Strong guarantee.
348 : Calls to allocate may throw.
349 : Exceptions thrown on invalid input.
350 :
351 : @throw system_error
352 : The range contains an invalid percent-encoding.
353 :
354 : @param first The first element in the range.
355 : @param last One past the last element in the range.
356 : */
357 : template<class FwdIt>
358 : void
359 : assign(FwdIt first, FwdIt last);
360 :
361 : //--------------------------------------------
362 :
363 : /** Insert segments
364 :
365 : This function inserts a segment
366 : before the specified position.
367 : Reserved characters in the segment are
368 : automatically escaped.
369 : Escapes in the segment are preserved.
370 :
371 : <br>
372 : All iterators that are equal to
373 : `before` or come after are invalidated.
374 :
375 : @par Complexity
376 : Linear in `s.size() + this->url().encoded_resource().size()`.
377 :
378 : @par Exception Safety
379 : Strong guarantee.
380 : Calls to allocate may throw.
381 : Exceptions thrown on invalid input.
382 :
383 : @throw system_error
384 : The segment contains an invalid percent-encoding.
385 :
386 : @return An iterator to the inserted
387 : segment.
388 :
389 : @param before An iterator before which
390 : the segment is inserted. This may
391 : be equal to `end()`.
392 :
393 : @param s The segment to insert.
394 : */
395 : BOOST_URL_DECL
396 : iterator
397 : insert(
398 : iterator before,
399 : pct_string_view s);
400 :
401 : /** Insert segments
402 :
403 : This function inserts the segments
404 : in an initializer list before the
405 : specified position.
406 : Reserved characters in the list are
407 : automatically escaped.
408 : Escapes in the list are preserved.
409 :
410 : <br>
411 : All iterators that are equal to
412 : `before` or come after are invalidated.
413 :
414 : @note
415 : None of the character buffers referenced
416 : by the list may overlap the character
417 : buffer of the underlying url, or else
418 : the behavior is undefined.
419 :
420 : @par Example
421 : @code
422 : url u( "/file.txt" );
423 :
424 : u.encoded_segments().insert( u.encoded_segments().begin(), { "path", "to" } );
425 : @endcode
426 :
427 : @par Complexity
428 : Linear in `init.size() + this->url().encoded_resource().size()`.
429 :
430 : @par Exception Safety
431 : Strong guarantee.
432 : Calls to allocate may throw.
433 : Exceptions thrown on invalid input.
434 :
435 : @throw system_error
436 : The list contains an invalid percent-encoding.
437 :
438 : @return An iterator to the first
439 : element inserted, or `before` if
440 : `init.size() == 0`.
441 :
442 : @param before An iterator before which
443 : the list is inserted. This may
444 : be equal to `end()`.
445 :
446 : @param init The list of segments to insert.
447 : */
448 : BOOST_URL_DECL
449 : iterator
450 : insert(
451 : iterator before,
452 : std::initializer_list<
453 : pct_string_view> init);
454 :
455 : /** Insert segments
456 :
457 : This function inserts the segments in
458 : a range before the specified position.
459 : Reserved characters in the range are
460 : automatically escaped.
461 : Escapes in the range are preserved.
462 :
463 : <br>
464 : All iterators that are equal to
465 : `before` or come after are invalidated.
466 :
467 : @note
468 : None of the character buffers referenced
469 : by the range may overlap the character
470 : buffer of the underlying url, or else
471 : the behavior is undefined.
472 :
473 : @par Mandates
474 : @code
475 : std::is_convertible< std::iterator_traits< FwdIt >::reference_type, pct_string_view >::value == true
476 : @endcode
477 :
478 : @par Complexity
479 : Linear in `std::distance( first, last ) + this->url().encoded_resource().size()`.
480 :
481 : @par Exception Safety
482 : Strong guarantee.
483 : Calls to allocate may throw.
484 : Exceptions thrown on invalid input.
485 :
486 : @throw system_error
487 : The range contains an invalid percent-encoding.
488 :
489 : @return An iterator to the first
490 : segment inserted, or `before` if
491 : `init.empty()`.
492 :
493 : @param before An iterator before which
494 : the range is inserted. This may
495 : be equal to `end()`.
496 :
497 : @param first The first element in the range to insert.
498 : @param last One past the last element in the range to insert.
499 : */
500 : template<class FwdIt>
501 : iterator
502 : insert(
503 : iterator before,
504 : FwdIt first,
505 : FwdIt last);
506 :
507 : //--------------------------------------------
508 :
509 : /** Erase segments
510 :
511 : This function removes a segment.
512 :
513 : <br>
514 : All iterators that are equal to
515 : `pos` or come after are invalidated.
516 :
517 : @par Complexity
518 : Linear in `this->url().encoded_resource().size()`.
519 :
520 : @par Exception Safety
521 : Throws nothing.
522 :
523 : @return An iterator to one past
524 : the removed segment.
525 :
526 : @param pos An iterator to the element.
527 : */
528 : iterator
529 : erase(
530 : iterator pos) noexcept;
531 :
532 : /** Erase segments
533 :
534 : This function removes a range of segments
535 : from the container.
536 :
537 : <br>
538 : All iterators that are equal to
539 : `first` or come after are invalidated.
540 :
541 : @par Complexity
542 : Linear in `this->url().encoded_resource().size()`.
543 :
544 : @par Exception Safety
545 : Throws nothing.
546 :
547 : @param first The first element in the range to erase.
548 : @param last One past the last element in the range to erase.
549 : @return An iterator to one past the removed range.
550 : */
551 : BOOST_URL_DECL
552 : iterator
553 : erase(
554 : iterator first,
555 : iterator last) noexcept;
556 :
557 : //--------------------------------------------
558 :
559 : /** Replace segments
560 :
561 : This function replaces the segment at
562 : the specified position.
563 : Reserved characters in the string are
564 : automatically escaped.
565 : Escapes in the string are preserved.
566 :
567 : <br>
568 : All iterators that are equal to
569 : `pos` or come after are invalidated.
570 :
571 : @par Complexity
572 : Linear in `s.size() + this->url().encoded_resouce().size()`.
573 :
574 : @par Exception Safety
575 : Strong guarantee.
576 : Calls to allocate may throw.
577 :
578 : @return An iterator to the replaced segment.
579 :
580 : @param pos An iterator to the segment.
581 :
582 : @param s The string to assign.
583 : */
584 : BOOST_URL_DECL
585 : iterator
586 : replace(
587 : iterator pos,
588 : pct_string_view s);
589 :
590 : /** Replace segments
591 :
592 : This function replaces a range of
593 : segments with one segment.
594 : Reserved characters in the string are
595 : automatically escaped.
596 : Escapes in the string are preserved.
597 :
598 : <br>
599 : All iterators that are equal to
600 : `from` or come after are invalidated.
601 :
602 : @par Complexity
603 : Linear in `s.size() + this->url().encoded_resouce().size()`.
604 :
605 : @par Exception Safety
606 : Strong guarantee.
607 : Calls to allocate may throw.
608 : Exceptions thrown on invalid input.
609 :
610 : @throw system_error
611 : The string contains an invalid percent-encoding.
612 :
613 : @return An iterator to the new segment.
614 :
615 : @param from The first element in the range of segments to replace.
616 : @param to One past the last element in the range of segments to replace.
617 :
618 : @param s The string to assign.
619 : */
620 : BOOST_URL_DECL
621 : iterator
622 : replace(
623 : iterator from,
624 : iterator to,
625 : pct_string_view s);
626 :
627 : /** Replace segments
628 :
629 : This function replaces a range of
630 : segments with a list of segments in
631 : an initializer list.
632 : Reserved characters in the list are
633 : automatically escaped.
634 : Escapes in the list are preserved.
635 :
636 : <br>
637 : All iterators that are equal to
638 : `from` or come after are invalidated.
639 :
640 : @par Preconditions
641 : None of the character buffers referenced
642 : by the list may overlap the character
643 : buffer of the underlying url, or else
644 : the behavior is undefined.
645 :
646 : @par Complexity
647 : Linear in `init.size() + this->url().encoded_resouce().size()`.
648 :
649 : @par Exception Safety
650 : Strong guarantee.
651 : Calls to allocate may throw.
652 : Exceptions thrown on invalid input.
653 :
654 : @throw system_error
655 : The list contains an invalid percent-encoding.
656 :
657 : @return An iterator to the first
658 : segment inserted, or one past `to` if
659 : `init.size() == 0`.
660 :
661 : @param from The first element in the range of segments to replace.
662 : @param to One past the last element in the range of segments to replace.
663 :
664 : @param init The list of segments to assign.
665 : */
666 : BOOST_URL_DECL
667 : iterator
668 : replace(
669 : iterator from,
670 : iterator to,
671 : std::initializer_list<
672 : pct_string_view> init);
673 :
674 : /** Replace segments
675 :
676 : This function replaces a range of
677 : segments with annother range of segments.
678 : Reserved characters in the new range are
679 : automatically escaped.
680 : Escapes in the new range are preserved.
681 :
682 : <br>
683 : All iterators that are equal to
684 : `from` or come after are invalidated.
685 :
686 : @par Preconditions
687 : None of the character buffers referenced
688 : by the new range may overlap the character
689 : buffer of the underlying url, or else
690 : the behavior is undefined.
691 :
692 : @par Complexity
693 : Linear in `std::distance( first, last ) + this->url().encoded_resouce().size()`.
694 :
695 : @par Exception Safety
696 : Strong guarantee.
697 : Calls to allocate may throw.
698 : Exceptions thrown on invalid input.
699 :
700 : @throw system_error
701 : The range contains an invalid percent-encoding.
702 :
703 : @return An iterator to the first
704 : segment inserted, or one past `to` if
705 : `init.size() == 0`.
706 :
707 : @param from The first element in the range of segments to replace.
708 : @param to One past the last element in the range of segments to replace.
709 : @param first The first element in the new range of segments.
710 : @param last One past the last element in the new range of segments.
711 : */
712 : template<class FwdIt>
713 : iterator
714 : replace(
715 : iterator from,
716 : iterator to,
717 : FwdIt first,
718 : FwdIt last);
719 :
720 : //--------------------------------------------
721 :
722 : /** Append a segment
723 :
724 : This function appends a segment to
725 : the end of the path.
726 : Reserved characters in the string are
727 : automatically escaped.
728 : Escapes in the string are preserved.
729 :
730 : <br>
731 : All end iterators are invalidated.
732 :
733 : @par Postconditions
734 : @code
735 : this->back() == s
736 : @endcode
737 :
738 : @par Exception Safety
739 : Strong guarantee.
740 : Calls to allocate may throw.
741 : Exceptions thrown on invalid input.
742 :
743 : @throw system_error
744 : The string contains an invalid percent-encoding.
745 :
746 : @param s The segment to append.
747 : */
748 : void
749 : push_back(
750 : pct_string_view s);
751 :
752 : /** Remove the last segment
753 :
754 : This function removes the last segment
755 : from the container.
756 :
757 : <br>
758 : Iterators to the last segment as well
759 : as all end iterators are invalidated.
760 :
761 : @par Preconditions
762 : @code
763 : !this->empty()
764 : @endcode
765 :
766 : @par Exception Safety
767 : Throws nothing.
768 : */
769 : void
770 : pop_back() noexcept;
771 :
772 : private:
773 : template<class FwdIt>
774 : iterator
775 : insert(
776 : iterator before,
777 : FwdIt first,
778 : FwdIt last,
779 : std::input_iterator_tag) = delete;
780 :
781 : template<class FwdIt>
782 : iterator
783 : insert(
784 : iterator before,
785 : FwdIt first,
786 : FwdIt last,
787 : std::forward_iterator_tag);
788 : };
789 :
790 : } // urls
791 : } // boost
792 :
793 : // This is in <boost/url/url_base.hpp>
794 : //
795 : // #include <boost/url/impl/segments_encoded_ref.hpp>
796 :
797 : #endif
|