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 : */
158 : BOOST_URL_DECL
159 : segments_encoded_ref&
160 : operator=(segments_encoded_ref const& other);
161 :
162 : /// @copydoc operator=(segments_encoded_ref const&)
163 : BOOST_URL_DECL
164 : segments_encoded_ref&
165 : operator=(segments_encoded_view const& other);
166 :
167 : /** Assignment
168 :
169 : The existing contents are replaced
170 : by a copy of the contents of the
171 : initializer list.
172 : Reserved characters in the list are
173 : automatically escaped.
174 : Escapes in the list are preserved.
175 :
176 : <br>
177 : All iterators are invalidated.
178 :
179 : @par Example
180 : @code
181 : url u;
182 :
183 : u.encoded_segments() = {"path", "to", "file.txt"};
184 : @endcode
185 :
186 : @par Preconditions
187 : None of the character buffers referenced
188 : by the list may overlap the character buffer
189 : of the underlying url, or else the behavior
190 : is undefined.
191 :
192 : @par Effects
193 : @code
194 : this->assign( init.begin(), init.end() );
195 : @endcode
196 :
197 : @par Complexity
198 : Linear in `init.size() + this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
199 :
200 : @par Exception Safety
201 : Strong guarantee.
202 : Calls to allocate may throw.
203 : Exceptions thrown on invalid input.
204 :
205 : @throw system_error
206 : The list contains an invalid percent-encoding.
207 :
208 : @param init The list of segments to assign.
209 : */
210 : BOOST_URL_DECL
211 : segments_encoded_ref&
212 : operator=(std::initializer_list<
213 : pct_string_view> init);
214 :
215 : /** Conversion
216 :
217 : @see
218 : @ref segments_encoded_view.
219 : */
220 : BOOST_URL_DECL
221 : operator
222 : segments_encoded_view() const noexcept;
223 :
224 : //--------------------------------------------
225 : //
226 : // Observers
227 : //
228 : //--------------------------------------------
229 :
230 : /** Return the referenced url
231 :
232 : This function returns the url referenced
233 : by the view.
234 :
235 : @par Example
236 : @code
237 : url u( "/path/to/file.txt" );
238 :
239 : assert( &u.encoded_segments().url() == &u );
240 : @endcode
241 :
242 : @par Exception Safety
243 : Throws nothing.
244 : */
245 : url_base&
246 9 : url() const noexcept
247 : {
248 9 : return *u_;
249 : }
250 :
251 : //--------------------------------------------
252 : //
253 : // Modifiers
254 : //
255 : //--------------------------------------------
256 :
257 : /** Clear the contents of the container
258 :
259 : <br>
260 : All iterators are invalidated.
261 :
262 : @par Effects
263 : @code
264 : this->url().set_encoded_path( "" );
265 : @endcode
266 :
267 : @par Postconditions
268 : @code
269 : this->empty() == true
270 : @endcode
271 :
272 : @par Complexity
273 : Linear in `this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
274 :
275 : @par Exception Safety
276 : Throws nothing.
277 : */
278 : void
279 : clear() noexcept;
280 :
281 : /** Assign segments
282 :
283 : The existing contents are replaced
284 : by a copy of the contents of the
285 : initializer list.
286 : Reserved characters in the list are
287 : automatically escaped.
288 : Escapes in the list are preserved.
289 :
290 : <br>
291 : All iterators are invalidated.
292 :
293 : @note
294 : None of the character buffers referenced
295 : by the list may overlap the character
296 : buffer of the underlying url, or else
297 : the behavior is undefined.
298 :
299 : @par Example
300 : @code
301 : url u;
302 :
303 : u.segments().assign( {"path", "to", "file.txt"} );
304 : @endcode
305 :
306 : @par Complexity
307 : Linear in `init.size() + this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
308 :
309 : @par Exception Safety
310 : Strong guarantee.
311 : Calls to allocate may throw.
312 : Exceptions thrown on invalid input.
313 :
314 : @throw system_error
315 : The list contains an invalid percent-encoding.
316 :
317 : @param init The list of segments to assign.
318 : */
319 : BOOST_URL_DECL
320 : void
321 : assign(std::initializer_list<
322 : pct_string_view> init);
323 :
324 : /** Assign segments
325 :
326 : The existing contents are replaced
327 : by a copy of the contents of the range.
328 : Reserved characters in the range are
329 : automatically escaped.
330 : Escapes in the range are preserved.
331 :
332 : <br>
333 : All iterators are invalidated.
334 :
335 : @note
336 : None of the character buffers referenced
337 : by the range may overlap the character
338 : buffer of the underlying url, or else
339 : the behavior is undefined.
340 :
341 : @par Mandates
342 : @code
343 : std::is_convertible< std::iterator_traits< FwdIt >::reference_type, pct_string_view >::value == true
344 : @endcode
345 :
346 : @par Complexity
347 : Linear in `std::distance( first, last ) + this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
348 :
349 : @par Exception Safety
350 : Strong guarantee.
351 : Calls to allocate may throw.
352 : Exceptions thrown on invalid input.
353 :
354 : @throw system_error
355 : The range contains an invalid percent-encoding.
356 :
357 : @param first The first element in the range.
358 : @param last One past the last element in the range.
359 : */
360 : template<class FwdIt>
361 : void
362 : assign(FwdIt first, FwdIt last);
363 :
364 : //--------------------------------------------
365 :
366 : /** Insert segments
367 :
368 : This function inserts a segment
369 : before the specified position.
370 : Reserved characters in the segment are
371 : automatically escaped.
372 : Escapes in the segment are preserved.
373 :
374 : <br>
375 : All iterators that are equal to
376 : `before` or come after are invalidated.
377 :
378 : @par Complexity
379 : Linear in `s.size() + this->url().encoded_resource().size()`.
380 :
381 : @par Exception Safety
382 : Strong guarantee.
383 : Calls to allocate may throw.
384 : Exceptions thrown on invalid input.
385 :
386 : @throw system_error
387 : The segment contains an invalid percent-encoding.
388 :
389 : @return An iterator to the inserted
390 : segment.
391 :
392 : @param before An iterator before which
393 : the segment is inserted. This may
394 : be equal to `end()`.
395 :
396 : @param s The segment to insert.
397 : */
398 : BOOST_URL_DECL
399 : iterator
400 : insert(
401 : iterator before,
402 : pct_string_view s);
403 :
404 : /** Insert segments
405 :
406 : This function inserts the segments
407 : in an initializer list before the
408 : specified position.
409 : Reserved characters in the list are
410 : automatically escaped.
411 : Escapes in the list are preserved.
412 :
413 : <br>
414 : All iterators that are equal to
415 : `before` or come after are invalidated.
416 :
417 : @note
418 : None of the character buffers referenced
419 : by the list may overlap the character
420 : buffer of the underlying url, or else
421 : the behavior is undefined.
422 :
423 : @par Example
424 : @code
425 : url u( "/file.txt" );
426 :
427 : u.encoded_segments().insert( u.encoded_segments().begin(), { "path", "to" } );
428 : @endcode
429 :
430 : @par Complexity
431 : Linear in `init.size() + this->url().encoded_resource().size()`.
432 :
433 : @par Exception Safety
434 : Strong guarantee.
435 : Calls to allocate may throw.
436 : Exceptions thrown on invalid input.
437 :
438 : @throw system_error
439 : The list contains an invalid percent-encoding.
440 :
441 : @return An iterator to the first
442 : element inserted, or `before` if
443 : `init.size() == 0`.
444 :
445 : @param before An iterator before which
446 : the list is inserted. This may
447 : be equal to `end()`.
448 :
449 : @param init The list of segments to insert.
450 : */
451 : BOOST_URL_DECL
452 : iterator
453 : insert(
454 : iterator before,
455 : std::initializer_list<
456 : pct_string_view> init);
457 :
458 : /** Insert segments
459 :
460 : This function inserts the segments in
461 : a range before the specified position.
462 : Reserved characters in the range are
463 : automatically escaped.
464 : Escapes in the range are preserved.
465 :
466 : <br>
467 : All iterators that are equal to
468 : `before` or come after are invalidated.
469 :
470 : @note
471 : None of the character buffers referenced
472 : by the range may overlap the character
473 : buffer of the underlying url, or else
474 : the behavior is undefined.
475 :
476 : @par Mandates
477 : @code
478 : std::is_convertible< std::iterator_traits< FwdIt >::reference_type, pct_string_view >::value == true
479 : @endcode
480 :
481 : @par Complexity
482 : Linear in `std::distance( first, last ) + this->url().encoded_resource().size()`.
483 :
484 : @par Exception Safety
485 : Strong guarantee.
486 : Calls to allocate may throw.
487 : Exceptions thrown on invalid input.
488 :
489 : @throw system_error
490 : The range contains an invalid percent-encoding.
491 :
492 : @return An iterator to the first
493 : segment inserted, or `before` if
494 : `init.empty()`.
495 :
496 : @param before An iterator before which
497 : the range is inserted. This may
498 : be equal to `end()`.
499 :
500 : @param first The first element in the range to insert.
501 : @param last One past the last element in the range to insert.
502 : */
503 : template<class FwdIt>
504 : iterator
505 : insert(
506 : iterator before,
507 : FwdIt first,
508 : FwdIt last);
509 :
510 : //--------------------------------------------
511 :
512 : /** Erase segments
513 :
514 : This function removes a segment.
515 :
516 : <br>
517 : All iterators that are equal to
518 : `pos` or come after are invalidated.
519 :
520 : @par Complexity
521 : Linear in `this->url().encoded_resource().size()`.
522 :
523 : @par Exception Safety
524 : Throws nothing.
525 :
526 : @return An iterator to one past
527 : the removed segment.
528 :
529 : @param pos An iterator to the element.
530 : */
531 : iterator
532 : erase(
533 : iterator pos) noexcept;
534 :
535 : /** Erase segments
536 :
537 : This function removes a range of segments
538 : from the container.
539 :
540 : <br>
541 : All iterators that are equal to
542 : `first` or come after are invalidated.
543 :
544 : @par Complexity
545 : Linear in `this->url().encoded_resource().size()`.
546 :
547 : @par Exception Safety
548 : Throws nothing.
549 :
550 : @return An iterator to one past
551 : the removed range.
552 :
553 : @param first, last The range of
554 : segments to erase.
555 : */
556 : BOOST_URL_DECL
557 : iterator
558 : erase(
559 : iterator first,
560 : iterator last) noexcept;
561 :
562 : //--------------------------------------------
563 :
564 : /** Replace segments
565 :
566 : This function replaces the segment at
567 : the specified position.
568 : Reserved characters in the string are
569 : automatically escaped.
570 : Escapes in the string are preserved.
571 :
572 : <br>
573 : All iterators that are equal to
574 : `pos` or come after are invalidated.
575 :
576 : @par Complexity
577 : Linear in `s.size() + this->url().encoded_resouce().size()`.
578 :
579 : @par Exception Safety
580 : Strong guarantee.
581 : Calls to allocate may throw.
582 :
583 : @return An iterator to the replaced segment.
584 :
585 : @param pos An iterator to the segment.
586 :
587 : @param s The string to assign.
588 : */
589 : BOOST_URL_DECL
590 : iterator
591 : replace(
592 : iterator pos,
593 : pct_string_view s);
594 :
595 : /** Replace segments
596 :
597 : This function replaces a range of
598 : segments with one segment.
599 : Reserved characters in the string are
600 : automatically escaped.
601 : Escapes in the string are preserved.
602 :
603 : <br>
604 : All iterators that are equal to
605 : `from` or come after are invalidated.
606 :
607 : @par Complexity
608 : Linear in `s.size() + this->url().encoded_resouce().size()`.
609 :
610 : @par Exception Safety
611 : Strong guarantee.
612 : Calls to allocate may throw.
613 : Exceptions thrown on invalid input.
614 :
615 : @throw system_error
616 : The string contains an invalid percent-encoding.
617 :
618 : @return An iterator to the new segment.
619 :
620 : @param from The first element in the range of segments to replace.
621 : @param to One past the last element in the range of segments to replace.
622 :
623 : @param s The string to assign.
624 : */
625 : BOOST_URL_DECL
626 : iterator
627 : replace(
628 : iterator from,
629 : iterator to,
630 : pct_string_view s);
631 :
632 : /** Replace segments
633 :
634 : This function replaces a range of
635 : segments with a list of segments in
636 : an initializer list.
637 : Reserved characters in the list are
638 : automatically escaped.
639 : Escapes in the list are preserved.
640 :
641 : <br>
642 : All iterators that are equal to
643 : `from` or come after are invalidated.
644 :
645 : @par Preconditions
646 : None of the character buffers referenced
647 : by the list may overlap the character
648 : buffer of the underlying url, or else
649 : the behavior is undefined.
650 :
651 : @par Complexity
652 : Linear in `init.size() + this->url().encoded_resouce().size()`.
653 :
654 : @par Exception Safety
655 : Strong guarantee.
656 : Calls to allocate may throw.
657 : Exceptions thrown on invalid input.
658 :
659 : @throw system_error
660 : The list contains an invalid percent-encoding.
661 :
662 : @return An iterator to the first
663 : segment inserted, or one past `to` if
664 : `init.size() == 0`.
665 :
666 : @param from The first element in the range of segments to replace.
667 : @param to One past the last element in the range of segments to replace.
668 :
669 : @param init The list of segments to assign.
670 : */
671 : BOOST_URL_DECL
672 : iterator
673 : replace(
674 : iterator from,
675 : iterator to,
676 : std::initializer_list<
677 : pct_string_view> init);
678 :
679 : /** Replace segments
680 :
681 : This function replaces a range of
682 : segments with annother range of segments.
683 : Reserved characters in the new range are
684 : automatically escaped.
685 : Escapes in the new range are preserved.
686 :
687 : <br>
688 : All iterators that are equal to
689 : `from` or come after are invalidated.
690 :
691 : @par Preconditions
692 : None of the character buffers referenced
693 : by the new range may overlap the character
694 : buffer of the underlying url, or else
695 : the behavior is undefined.
696 :
697 : @par Complexity
698 : Linear in `std::distance( first, last ) + this->url().encoded_resouce().size()`.
699 :
700 : @par Exception Safety
701 : Strong guarantee.
702 : Calls to allocate may throw.
703 : Exceptions thrown on invalid input.
704 :
705 : @throw system_error
706 : The range contains an invalid percent-encoding.
707 :
708 : @return An iterator to the first
709 : segment inserted, or one past `to` if
710 : `init.size() == 0`.
711 :
712 : @param from The first element in the range of segments to replace.
713 : @param to One past the last element in the range of segments to replace.
714 : @param first The first element in the new range of segments.
715 : @param last One past the last element in the new range of segments.
716 : */
717 : template<class FwdIt>
718 : iterator
719 : replace(
720 : iterator from,
721 : iterator to,
722 : FwdIt first,
723 : FwdIt last);
724 :
725 : //--------------------------------------------
726 :
727 : /** Append a segment
728 :
729 : This function appends a segment to
730 : the end of the path.
731 : Reserved characters in the string are
732 : automatically escaped.
733 : Escapes in the string are preserved.
734 :
735 : <br>
736 : All end iterators are invalidated.
737 :
738 : @par Postconditions
739 : @code
740 : this->back() == s
741 : @endcode
742 :
743 : @par Exception Safety
744 : Strong guarantee.
745 : Calls to allocate may throw.
746 : Exceptions thrown on invalid input.
747 :
748 : @throw system_error
749 : The string contains an invalid percent-encoding.
750 :
751 : @param s The segment to append.
752 : */
753 : void
754 : push_back(
755 : pct_string_view s);
756 :
757 : /** Remove the last segment
758 :
759 : This function removes the last segment
760 : from the container.
761 :
762 : <br>
763 : Iterators to the last segment as well
764 : as all end iterators are invalidated.
765 :
766 : @par Preconditions
767 : @code
768 : !this->empty()
769 : @endcode
770 :
771 : @par Exception Safety
772 : Throws nothing.
773 : */
774 : void
775 : pop_back() noexcept;
776 :
777 : private:
778 : template<class FwdIt>
779 : iterator
780 : insert(
781 : iterator before,
782 : FwdIt first,
783 : FwdIt last,
784 : std::input_iterator_tag) = delete;
785 :
786 : template<class FwdIt>
787 : iterator
788 : insert(
789 : iterator before,
790 : FwdIt first,
791 : FwdIt last,
792 : std::forward_iterator_tag);
793 : };
794 :
795 : } // urls
796 : } // boost
797 :
798 : // This is in <boost/url/url_base.hpp>
799 : //
800 : // #include <boost/url/impl/segments_encoded_ref.hpp>
801 :
802 : #endif
|