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