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