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