include/boost/url/segments_ref.hpp

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