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