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