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