1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3  
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
3  
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
4  
//
4  
//
5  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
6  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  
//
7  
//
8  
// Official repository: https://github.com/boostorg/url
8  
// Official repository: https://github.com/boostorg/url
9  
//
9  
//
10  

10  

11  
#ifndef BOOST_URL_SEGMENTS_REF_HPP
11  
#ifndef BOOST_URL_SEGMENTS_REF_HPP
12  
#define BOOST_URL_SEGMENTS_REF_HPP
12  
#define BOOST_URL_SEGMENTS_REF_HPP
13  

13  

14  
#include <boost/url/detail/config.hpp>
14  
#include <boost/url/detail/config.hpp>
15  
#include <boost/url/segments_base.hpp>
15  
#include <boost/url/segments_base.hpp>
16  
#include <initializer_list>
16  
#include <initializer_list>
17  
#include <iterator>
17  
#include <iterator>
18  

18  

19  
namespace boost {
19  
namespace boost {
20  
namespace urls {
20  
namespace urls {
21  

21  

22  
#ifndef BOOST_URL_DOCS
22  
#ifndef BOOST_URL_DOCS
23  
class url_base;
23  
class url_base;
24  
class segments_view;
24  
class segments_view;
25  
#endif
25  
#endif
26  

26  

27  
/** Mutable decoded path segment proxy
27  
/** Mutable decoded path segment proxy
28  

28  

29  
    Presents the decoded path segments of a
29  
    Presents the decoded path segments of a
30  
    @ref url_base as a bidirectional range whose
30  
    @ref url_base as a bidirectional range whose
31  
    modifiers update the underlying URL. The proxy
31  
    modifiers update the underlying URL. The proxy
32  
    references the URL’s storage directly, so the
32  
    references the URL’s storage directly, so the
33  
    owning URL must remain alive while the proxy
33  
    owning URL must remain alive while the proxy
34  
    is used.
34  
    is used.
35  

35  

36  
    @par Example
36  
    @par Example
37  
    @code
37  
    @code
38  
    url u( "/path/to/file.txt" );
38  
    url u( "/path/to/file.txt" );
39  

39  

40  
    segments_ref ps = u.segments();
40  
    segments_ref ps = u.segments();
41  
    @endcode
41  
    @endcode
42  

42  

43  
    Percent escapes in strings returned when
43  
    Percent escapes in strings returned when
44  
    dereferencing iterators are automatically
44  
    dereferencing iterators are automatically
45  
    decoded.
45  
    decoded.
46  
    Reserved characters in strings supplied
46  
    Reserved characters in strings supplied
47  
    to modifier functions are automatically
47  
    to modifier functions are automatically
48  
    percent-escaped.
48  
    percent-escaped.
49  

49  

50  
    @par Iterator Invalidation
50  
    @par Iterator Invalidation
51  
    Changes to the underlying character buffer
51  
    Changes to the underlying character buffer
52  
    can invalidate iterators which reference it.
52  
    can invalidate iterators which reference it.
53  
    Modifications made through the container
53  
    Modifications made through the container
54  
    invalidate some or all iterators:
54  
    invalidate some or all iterators:
55  
    <br>
55  
    <br>
56  

56  

57  
    @li @ref push_back : Only `end()`.
57  
    @li @ref push_back : Only `end()`.
58  

58  

59  
    @li @ref assign, @ref clear,
59  
    @li @ref assign, @ref clear,
60  
        @ref operator= : All elements.
60  
        @ref operator= : All elements.
61  

61  

62  
    @li @ref erase : Erased elements and all
62  
    @li @ref erase : Erased elements and all
63  
        elements after (including `end()`).
63  
        elements after (including `end()`).
64  

64  

65  
    @li @ref insert : All elements at or after
65  
    @li @ref insert : All elements at or after
66  
        the insertion point (including `end()`).
66  
        the insertion point (including `end()`).
67  

67  

68  
    @li @ref replace : Modified
68  
    @li @ref replace : Modified
69  
        elements and all elements
69  
        elements and all elements
70  
        after (including `end()`).
70  
        after (including `end()`).
71  

71  

72  
    @see
72  
    @see
73  
        @ref segments_encoded_ref,
73  
        @ref segments_encoded_ref,
74  
        @ref segments_encoded_view,
74  
        @ref segments_encoded_view,
75  
        @ref segments_view.
75  
        @ref segments_view.
76  
*/
76  
*/
77  
class BOOST_SYMBOL_VISIBLE segments_ref
77  
class BOOST_SYMBOL_VISIBLE segments_ref
78  
    : public segments_base
78  
    : public segments_base
79  
{
79  
{
80  
    url_base* u_ = nullptr;
80  
    url_base* u_ = nullptr;
81  

81  

82  
    friend class url_base;
82  
    friend class url_base;
83  
    friend class segments_encoded_ref;
83  
    friend class segments_encoded_ref;
84  

84  

85  
    segments_ref(url_base& u) noexcept;
85  
    segments_ref(url_base& u) noexcept;
86  

86  

87  
public:
87  
public:
88  
    //--------------------------------------------
88  
    //--------------------------------------------
89  
    //
89  
    //
90  
    // Special Members
90  
    // Special Members
91  
    //
91  
    //
92  
    //--------------------------------------------
92  
    //--------------------------------------------
93  

93  

94  
    /** Constructor
94  
    /** Constructor
95  

95  

96  
        After construction, both views
96  
        After construction, both views
97  
        reference the same url. Ownership is not
97  
        reference the same url. Ownership is not
98  
        transferred; the caller is responsible
98  
        transferred; the caller is responsible
99  
        for ensuring the lifetime of the url
99  
        for ensuring the lifetime of the url
100  
        extends until it is no longer
100  
        extends until it is no longer
101  
        referenced.
101  
        referenced.
102  

102  

103  
        @par Postconditions
103  
        @par Postconditions
104  
        @code
104  
        @code
105  
        &this->url() == &other.url();
105  
        &this->url() == &other.url();
106  
        @endcode
106  
        @endcode
107  

107  

108  
        @par Complexity
108  
        @par Complexity
109  
        Constant.
109  
        Constant.
110  

110  

111  
        @par Exception Safety
111  
        @par Exception Safety
112  
        Throws nothing.
112  
        Throws nothing.
113  

113  

114  
        @param other The other view.
114  
        @param other The other view.
115  
    */
115  
    */
116  
    segments_ref(
116  
    segments_ref(
117  
        segments_ref const& other) = default;
117  
        segments_ref const& other) = default;
118  

118  

119  
    /** Assignment
119  
    /** Assignment
120  

120  

121  
        The existing contents are replaced
121  
        The existing contents are replaced
122  
        by a copy of the other segments.
122  
        by a copy of the other segments.
123  

123  

124  
        <br>
124  
        <br>
125  
        All iterators are invalidated.
125  
        All iterators are invalidated.
126  

126  

127  
        @note
127  
        @note
128  
        None of the character buffers referenced
128  
        None of the character buffers referenced
129  
        by `other` may overlap the buffer of the
129  
        by `other` may overlap the buffer of the
130  
        underlying url, or else the behavior
130  
        underlying url, or else the behavior
131  
        is undefined.
131  
        is undefined.
132  

132  

133  
        @par Effects
133  
        @par Effects
134  
        @code
134  
        @code
135  
        this->assign( other.begin(), other.end() );
135  
        this->assign( other.begin(), other.end() );
136  
        @endcode
136  
        @endcode
137  

137  

138  
        @par Complexity
138  
        @par Complexity
139  
        Linear in `other.buffer().size()`.
139  
        Linear in `other.buffer().size()`.
140  

140  

141  
        @par Exception Safety
141  
        @par Exception Safety
142  
        Strong guarantee.
142  
        Strong guarantee.
143  
        Calls to allocate may throw.
143  
        Calls to allocate may throw.
144  

144  

145  
        @param other The segments to assign.
145  
        @param other The segments to assign.
146  
        @return A reference to this object.
146  
        @return A reference to this object.
147  
    */
147  
    */
148  
    segments_ref&
148  
    segments_ref&
149  
    operator=(segments_ref const& other);
149  
    operator=(segments_ref const& other);
150  

150  

151  
    /// @copydoc segments_ref::operator=(segments_ref const&)
151  
    /// @copydoc segments_ref::operator=(segments_ref const&)
152  
    segments_ref&
152  
    segments_ref&
153  
    operator=(segments_view const& other);
153  
    operator=(segments_view const& other);
154  

154  

155  
    /** Assignment
155  
    /** Assignment
156  

156  

157  
        The existing contents are replaced
157  
        The existing contents are replaced
158  
        by a copy of the contents of the
158  
        by a copy of the contents of the
159  
        initializer list.
159  
        initializer list.
160  
        Reserved characters in the list are
160  
        Reserved characters in the list are
161  
        automatically escaped.
161  
        automatically escaped.
162  

162  

163  
        <br>
163  
        <br>
164  
        All iterators are invalidated.
164  
        All iterators are invalidated.
165  

165  

166  
        @par Example
166  
        @par Example
167  
        @code
167  
        @code
168  
        url u;
168  
        url u;
169  

169  

170  
        u.segments() = { "path", "to", "file.txt" };
170  
        u.segments() = { "path", "to", "file.txt" };
171  
        @endcode
171  
        @endcode
172  

172  

173  
        @par Preconditions
173  
        @par Preconditions
174  
        None of the character buffers referenced
174  
        None of the character buffers referenced
175  
        by the list may overlap the character
175  
        by the list may overlap the character
176  
        buffer of the underlying url, or else
176  
        buffer of the underlying url, or else
177  
        the behavior is undefined.
177  
        the behavior is undefined.
178  

178  

179  
        @par Effects
179  
        @par Effects
180  
        @code
180  
        @code
181  
        this->assign( init.begin(), init.end() );
181  
        this->assign( init.begin(), init.end() );
182  
        @endcode
182  
        @endcode
183  

183  

184  
        @par Complexity
184  
        @par Complexity
185  
        Linear in `init.size() + this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
185  
        Linear in `init.size() + this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
186  

186  

187  
        @par Exception Safety
187  
        @par Exception Safety
188  
        Strong guarantee.
188  
        Strong guarantee.
189  
        Calls to allocate may throw.
189  
        Calls to allocate may throw.
190  

190  

191  
        @param init The list of segments to assign.
191  
        @param init The list of segments to assign.
192  
        @return A reference to this object.
192  
        @return A reference to this object.
193  
    */
193  
    */
194  
    segments_ref&
194  
    segments_ref&
195  
    operator=(std::initializer_list<
195  
    operator=(std::initializer_list<
196  
        core::string_view> init);
196  
        core::string_view> init);
197  

197  

198  
    /** Conversion
198  
    /** Conversion
199  

199  

200  
        @see
200  
        @see
201  
            @ref segments_view.
201  
            @ref segments_view.
202  

202  

203  
        @return A view of the segments.
203  
        @return A view of the segments.
204  
    */
204  
    */
205  
    operator
205  
    operator
206  
    segments_view() const noexcept;
206  
    segments_view() const noexcept;
207  

207  

208  
    //--------------------------------------------
208  
    //--------------------------------------------
209  
    //
209  
    //
210  
    // Observers
210  
    // Observers
211  
    //
211  
    //
212  
    //--------------------------------------------
212  
    //--------------------------------------------
213  

213  

214  
    /** Return the referenced url
214  
    /** Return the referenced url
215  

215  

216  
        This function returns the url referenced
216  
        This function returns the url referenced
217  
        by the view.
217  
        by the view.
218  

218  

219  
        @par Example
219  
        @par Example
220  
        @code
220  
        @code
221  
        url u( "/path/to/file.txt" );
221  
        url u( "/path/to/file.txt" );
222  

222  

223  
        assert( &u.segments().url() == &u );
223  
        assert( &u.segments().url() == &u );
224  
        @endcode
224  
        @endcode
225  

225  

226  
        @par Exception Safety
226  
        @par Exception Safety
227  
        Throws nothing.
227  
        Throws nothing.
228  

228  

229  
        @return A reference to the url.
229  
        @return A reference to the url.
230  
    */
230  
    */
231  
    url_base&
231  
    url_base&
232  
    url() const noexcept
232  
    url() const noexcept
233  
    {
233  
    {
234  
        return *u_;
234  
        return *u_;
235  
    }
235  
    }
236  

236  

237  
    //--------------------------------------------
237  
    //--------------------------------------------
238  
    //
238  
    //
239  
    // Modifiers
239  
    // Modifiers
240  
    //
240  
    //
241  
    //--------------------------------------------
241  
    //--------------------------------------------
242  

242  

243  
    /** Clear the contents of the container
243  
    /** Clear the contents of the container
244  

244  

245  
        <br>
245  
        <br>
246  
        All iterators are invalidated.
246  
        All iterators are invalidated.
247  

247  

248  
        @par Effects
248  
        @par Effects
249  
        @code
249  
        @code
250  
        this->url().set_encoded_path( "" );
250  
        this->url().set_encoded_path( "" );
251  
        @endcode
251  
        @endcode
252  

252  

253  
        @par Postconditions
253  
        @par Postconditions
254  
        @code
254  
        @code
255  
        this->empty() == true
255  
        this->empty() == true
256  
        @endcode
256  
        @endcode
257  

257  

258  
        @par Complexity
258  
        @par Complexity
259  
        Linear in `this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
259  
        Linear in `this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
260  

260  

261  
        @par Exception Safety
261  
        @par Exception Safety
262  
        Throws nothing.
262  
        Throws nothing.
263  
    */
263  
    */
264  
    void
264  
    void
265  
    clear() noexcept;
265  
    clear() noexcept;
266  

266  

267  
    /** Assign segments
267  
    /** Assign segments
268  

268  

269  
        The existing contents are replaced
269  
        The existing contents are replaced
270  
        by a copy of the contents of the
270  
        by a copy of the contents of the
271  
        initializer list.
271  
        initializer list.
272  
        Reserved characters in the list are
272  
        Reserved characters in the list are
273  
        automatically escaped.
273  
        automatically escaped.
274  

274  

275  
        <br>
275  
        <br>
276  
        All iterators are invalidated.
276  
        All iterators are invalidated.
277  

277  

278  
        @note
278  
        @note
279  
        None of the character buffers referenced
279  
        None of the character buffers referenced
280  
        by `init` may overlap the character buffer
280  
        by `init` may overlap the character buffer
281  
        of the underlying url, or else the behavior
281  
        of the underlying url, or else the behavior
282  
        is undefined.
282  
        is undefined.
283  

283  

284  
        @par Example
284  
        @par Example
285  
        @code
285  
        @code
286  
        url u;
286  
        url u;
287  

287  

288  
        u.segments().assign( { "path", "to", "file.txt" } );
288  
        u.segments().assign( { "path", "to", "file.txt" } );
289  
        @endcode
289  
        @endcode
290  

290  

291  
        @par Complexity
291  
        @par Complexity
292  
        Linear in `init.size() + this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
292  
        Linear in `init.size() + this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
293  

293  

294  
        @par Exception Safety
294  
        @par Exception Safety
295  
        Strong guarantee.
295  
        Strong guarantee.
296  
        Calls to allocate may throw.
296  
        Calls to allocate may throw.
297  

297  

298  
        @param init The list of segments to assign.
298  
        @param init The list of segments to assign.
299  
    */
299  
    */
300  
    void
300  
    void
301  
    assign(std::initializer_list<
301  
    assign(std::initializer_list<
302  
        core::string_view> init);
302  
        core::string_view> init);
303  

303  

304  
    /** Assign segments
304  
    /** Assign segments
305  

305  

306  
        The existing contents are replaced
306  
        The existing contents are replaced
307  
        by a copy of the contents of the range.
307  
        by a copy of the contents of the range.
308  
        Reserved characters in the range are
308  
        Reserved characters in the range are
309  
        automatically escaped.
309  
        automatically escaped.
310  

310  

311  
        <br>
311  
        <br>
312  
        All iterators are invalidated.
312  
        All iterators are invalidated.
313  

313  

314  
        @note
314  
        @note
315  
        None of the character buffers referenced
315  
        None of the character buffers referenced
316  
        by the range may overlap the character
316  
        by the range may overlap the character
317  
        buffer of the underlying url, or else
317  
        buffer of the underlying url, or else
318  
        the behavior is undefined.
318  
        the behavior is undefined.
319  

319  

320  
        @par Mandates
320  
        @par Mandates
321  
        @code
321  
        @code
322  
        std::is_convertible< std::iterator_traits< FwdIt >::reference_type, core::string_view >::value == true
322  
        std::is_convertible< std::iterator_traits< FwdIt >::reference_type, core::string_view >::value == true
323  
        @endcode
323  
        @endcode
324  

324  

325  
        @par Complexity
325  
        @par Complexity
326  
        Linear in `std::distance( first, last ) + this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
326  
        Linear in `std::distance( first, last ) + this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
327  

327  

328  
        @par Exception Safety
328  
        @par Exception Safety
329  
        Strong guarantee.
329  
        Strong guarantee.
330  
        Calls to allocate may throw.
330  
        Calls to allocate may throw.
331  

331  

332  
        @param first The beginning of the range of segments to assign.
332  
        @param first The beginning of the range of segments to assign.
333  
        @param last The end of the range of segments to assign.
333  
        @param last The end of the range of segments to assign.
334  
    */
334  
    */
335  
    template<class FwdIt>
335  
    template<class FwdIt>
336  
    void
336  
    void
337  
    assign(FwdIt first, FwdIt last);
337  
    assign(FwdIt first, FwdIt last);
338  

338  

339  
    //--------------------------------------------
339  
    //--------------------------------------------
340  

340  

341  
    /** Insert segments
341  
    /** Insert segments
342  

342  

343  
        This function inserts a segment
343  
        This function inserts a segment
344  
        before the specified position.
344  
        before the specified position.
345  
        Reserved characters in the segment are
345  
        Reserved characters in the segment are
346  
        automatically escaped.
346  
        automatically escaped.
347  

347  

348  
        <br>
348  
        <br>
349  
        All iterators that are equal to
349  
        All iterators that are equal to
350  
        `before` or come after are invalidated.
350  
        `before` or come after are invalidated.
351  

351  

352  
        @par Complexity
352  
        @par Complexity
353  
        Linear in `s.size() + this->url().encoded_resource().size()`.
353  
        Linear in `s.size() + this->url().encoded_resource().size()`.
354  

354  

355  
        @par Exception Safety
355  
        @par Exception Safety
356  
        Strong guarantee.
356  
        Strong guarantee.
357  
        Calls to allocate may throw.
357  
        Calls to allocate may throw.
358  

358  

359  
        @return An iterator to the inserted
359  
        @return An iterator to the inserted
360  
        segment.
360  
        segment.
361  

361  

362  
        @param before An iterator before which
362  
        @param before An iterator before which
363  
        the segment is inserted. This may
363  
        the segment is inserted. This may
364  
        be equal to `end()`.
364  
        be equal to `end()`.
365  

365  

366  
        @param s The segment to insert.
366  
        @param s The segment to insert.
367  
    */
367  
    */
368  
    iterator
368  
    iterator
369  
    insert(
369  
    insert(
370  
        iterator before,
370  
        iterator before,
371  
        core::string_view s);
371  
        core::string_view s);
372  

372  

373  
    /** Insert segments
373  
    /** Insert segments
374  

374  

375  
        This function inserts the segments
375  
        This function inserts the segments
376  
        in an initializer list before the
376  
        in an initializer list before the
377  
        specified position.
377  
        specified position.
378  
        Reserved characters in the list are
378  
        Reserved characters in the list are
379  
        percent-escaped in the result.
379  
        percent-escaped in the result.
380  

380  

381  
        <br>
381  
        <br>
382  
        All iterators that are equal to
382  
        All iterators that are equal to
383  
        `before` or come after are invalidated.
383  
        `before` or come after are invalidated.
384  

384  

385  
        @note
385  
        @note
386  
        None of the character buffers referenced
386  
        None of the character buffers referenced
387  
        by the list may overlap the character
387  
        by the list may overlap the character
388  
        buffer of the underlying url, or else
388  
        buffer of the underlying url, or else
389  
        the behavior is undefined.
389  
        the behavior is undefined.
390  

390  

391  
        @par Example
391  
        @par Example
392  
        @code
392  
        @code
393  
        url u( "/file.txt" );
393  
        url u( "/file.txt" );
394  

394  

395  
        u.segments().insert( u.segments().begin(), { "path", "to" } );
395  
        u.segments().insert( u.segments().begin(), { "path", "to" } );
396  
        @endcode
396  
        @endcode
397  

397  

398  
        @par Complexity
398  
        @par Complexity
399  
        Linear in `init.size() + this->url().encoded_resource().size()`.
399  
        Linear in `init.size() + this->url().encoded_resource().size()`.
400  

400  

401  
        @par Exception Safety
401  
        @par Exception Safety
402  
        Strong guarantee.
402  
        Strong guarantee.
403  
        Calls to allocate may throw.
403  
        Calls to allocate may throw.
404  

404  

405  
        @return An iterator to the first
405  
        @return An iterator to the first
406  
        element inserted, or `before` if
406  
        element inserted, or `before` if
407  
        `init.size() == 0`.
407  
        `init.size() == 0`.
408  

408  

409  
        @param before An iterator before which
409  
        @param before An iterator before which
410  
        the list is inserted. This may
410  
        the list is inserted. This may
411  
        be equal to `end()`.
411  
        be equal to `end()`.
412  

412  

413  
        @param init The list of segments to insert.
413  
        @param init The list of segments to insert.
414  
    */
414  
    */
415  
    iterator
415  
    iterator
416  
    insert(
416  
    insert(
417  
        iterator before,
417  
        iterator before,
418  
        std::initializer_list<core::string_view> init);
418  
        std::initializer_list<core::string_view> init);
419  

419  

420  
    /** Insert segments
420  
    /** Insert segments
421  

421  

422  
        This function inserts the segments in
422  
        This function inserts the segments in
423  
        a range before the specified position.
423  
        a range before the specified position.
424  
        Reserved characters in the list are
424  
        Reserved characters in the list are
425  
        automatically escaped.
425  
        automatically escaped.
426  

426  

427  
        <br>
427  
        <br>
428  
        All iterators that are equal to
428  
        All iterators that are equal to
429  
        `before` or come after are invalidated.
429  
        `before` or come after are invalidated.
430  

430  

431  
        @note
431  
        @note
432  
        None of the character buffers referenced
432  
        None of the character buffers referenced
433  
        by the range may overlap the character
433  
        by the range may overlap the character
434  
        buffer of the underlying url, or else
434  
        buffer of the underlying url, or else
435  
        the behavior is undefined.
435  
        the behavior is undefined.
436  

436  

437  
        @par Mandates
437  
        @par Mandates
438  
        @code
438  
        @code
439  
        std::is_convertible< std::iterator_traits< FwdIt >::reference_type, core::string_view >::value == true
439  
        std::is_convertible< std::iterator_traits< FwdIt >::reference_type, core::string_view >::value == true
440  
        @endcode
440  
        @endcode
441  

441  

442  
        @par Complexity
442  
        @par Complexity
443  
        Linear in `std::distance( first, last ) + this->url().encoded_resource().size()`.
443  
        Linear in `std::distance( first, last ) + this->url().encoded_resource().size()`.
444  

444  

445  
        @par Exception Safety
445  
        @par Exception Safety
446  
        Strong guarantee.
446  
        Strong guarantee.
447  
        Calls to allocate may throw.
447  
        Calls to allocate may throw.
448  

448  

449  
        @return An iterator to the first
449  
        @return An iterator to the first
450  
        segment inserted, or `before` if
450  
        segment inserted, or `before` if
451  
        `init.empty()`.
451  
        `init.empty()`.
452  

452  

453  
        @param before An iterator before which
453  
        @param before An iterator before which
454  
        the range is inserted. This may
454  
        the range is inserted. This may
455  
        be equal to `end()`.
455  
        be equal to `end()`.
456  

456  

457  
        @param first The beginning of the range of segments to insert.
457  
        @param first The beginning of the range of segments to insert.
458  
        @param last The end of the range of segments to insert.
458  
        @param last The end of the range of segments to insert.
459  
    */
459  
    */
460  
    template<class FwdIt>
460  
    template<class FwdIt>
461  
    iterator
461  
    iterator
462  
    insert(
462  
    insert(
463  
        iterator before,
463  
        iterator before,
464  
        FwdIt first,
464  
        FwdIt first,
465  
        FwdIt last);
465  
        FwdIt last);
466  

466  

467  
    //--------------------------------------------
467  
    //--------------------------------------------
468  

468  

469  
    /** Erase segments
469  
    /** Erase segments
470  

470  

471  
        This function removes a segment.
471  
        This function removes a segment.
472  

472  

473  
        <br>
473  
        <br>
474  
        All iterators that are equal to
474  
        All iterators that are equal to
475  
        `pos` or come after are invalidated.
475  
        `pos` or come after are invalidated.
476  

476  

477  
        @par Complexity
477  
        @par Complexity
478  
        Linear in `this->url().encoded_resource().size()`.
478  
        Linear in `this->url().encoded_resource().size()`.
479  

479  

480  
        @par Exception Safety
480  
        @par Exception Safety
481  
        Throws nothing.
481  
        Throws nothing.
482  

482  

483  
        @return An iterator to one past
483  
        @return An iterator to one past
484  
        the removed segment.
484  
        the removed segment.
485  

485  

486  
        @param pos An iterator to the segment.
486  
        @param pos An iterator to the segment.
487  
    */
487  
    */
488  
    iterator
488  
    iterator
489  
    erase(
489  
    erase(
490  
        iterator pos) noexcept;
490  
        iterator pos) noexcept;
491  

491  

492  
    /** Erase segments
492  
    /** Erase segments
493  

493  

494  
        This function removes a range of segments.
494  
        This function removes a range of segments.
495  

495  

496  
        <br>
496  
        <br>
497  
        All iterators that are equal to
497  
        All iterators that are equal to
498  
        `first` or come after are invalidated.
498  
        `first` or come after are invalidated.
499  

499  

500  
        @par Complexity
500  
        @par Complexity
501  
        Linear in `this->url().encoded_resource().size()`.
501  
        Linear in `this->url().encoded_resource().size()`.
502  

502  

503  
        @par Exception Safety
503  
        @par Exception Safety
504  
        Throws nothing.
504  
        Throws nothing.
505  

505  

506  
        @return An iterator to one past
506  
        @return An iterator to one past
507  
        the removed range.
507  
        the removed range.
508  

508  

509  
        @param first The beginning of the range to remove.
509  
        @param first The beginning of the range to remove.
510  
        @param last The end of the range to remove.
510  
        @param last The end of the range to remove.
511  
    */
511  
    */
512  
    iterator
512  
    iterator
513  
    erase(
513  
    erase(
514  
        iterator first,
514  
        iterator first,
515  
        iterator last) noexcept;
515  
        iterator last) noexcept;
516  

516  

517  
    //--------------------------------------------
517  
    //--------------------------------------------
518  

518  

519  
    /** Replace segments
519  
    /** Replace segments
520  

520  

521  
        This function replaces the segment at
521  
        This function replaces the segment at
522  
        the specified position.
522  
        the specified position.
523  
        Reserved characters in the string are
523  
        Reserved characters in the string are
524  
        automatically escaped.
524  
        automatically escaped.
525  

525  

526  
        <br>
526  
        <br>
527  
        All iterators that are equal to
527  
        All iterators that are equal to
528  
        `pos` or come after are invalidated.
528  
        `pos` or come after are invalidated.
529  

529  

530  
        @par Complexity
530  
        @par Complexity
531  
        Linear in `s.size() + this->url().encoded_resouce().size()`.
531  
        Linear in `s.size() + this->url().encoded_resouce().size()`.
532  

532  

533  
        @par Exception Safety
533  
        @par Exception Safety
534  
        Strong guarantee.
534  
        Strong guarantee.
535  
        Calls to allocate may throw.
535  
        Calls to allocate may throw.
536  

536  

537  
        @return An iterator to the replaced segment.
537  
        @return An iterator to the replaced segment.
538  

538  

539  
        @param pos An iterator to the segment.
539  
        @param pos An iterator to the segment.
540  

540  

541  
        @param s The string to assign.
541  
        @param s The string to assign.
542  
    */
542  
    */
543  
    iterator
543  
    iterator
544  
    replace(
544  
    replace(
545  
        iterator pos,
545  
        iterator pos,
546  
        core::string_view s);
546  
        core::string_view s);
547  

547  

548  
    /** Replace segments
548  
    /** Replace segments
549  

549  

550  
        This function replaces a range of
550  
        This function replaces a range of
551  
        segments with one segment.
551  
        segments with one segment.
552  
        Reserved characters in the string are
552  
        Reserved characters in the string are
553  
        automatically escaped.
553  
        automatically escaped.
554  

554  

555  
        <br>
555  
        <br>
556  
        All iterators that are equal to
556  
        All iterators that are equal to
557  
        `from` or come after are invalidated.
557  
        `from` or come after are invalidated.
558  

558  

559  
        @par Complexity
559  
        @par Complexity
560  
        Linear in `s.size() + this->url().encoded_resouce().size()`.
560  
        Linear in `s.size() + this->url().encoded_resouce().size()`.
561  

561  

562  
        @par Exception Safety
562  
        @par Exception Safety
563  
        Strong guarantee.
563  
        Strong guarantee.
564  
        Calls to allocate may throw.
564  
        Calls to allocate may throw.
565  

565  

566  
        @return An iterator to the new segment.
566  
        @return An iterator to the new segment.
567  

567  

568  
        @param from The beginning of the range of segments to replace.
568  
        @param from The beginning of the range of segments to replace.
569  
        @param to The end of the range of segments to replace.
569  
        @param to The end of the range of segments to replace.
570  

570  

571  
        @param s The string to assign.
571  
        @param s The string to assign.
572  
    */
572  
    */
573  
    iterator
573  
    iterator
574  
    replace(
574  
    replace(
575  
        iterator from,
575  
        iterator from,
576  
        iterator to,
576  
        iterator to,
577  
        core::string_view s);
577  
        core::string_view s);
578  

578  

579  
    /** Replace segments
579  
    /** Replace segments
580  

580  

581  
        This function replaces a range of
581  
        This function replaces a range of
582  
        segments with a list of segments in
582  
        segments with a list of segments in
583  
        an initializer list.
583  
        an initializer list.
584  
        Reserved characters in the list are
584  
        Reserved characters in the list are
585  
        automatically escaped.
585  
        automatically escaped.
586  

586  

587  
        <br>
587  
        <br>
588  
        All iterators that are equal to
588  
        All iterators that are equal to
589  
        `from` or come after are invalidated.
589  
        `from` or come after are invalidated.
590  

590  

591  
        @par Preconditions
591  
        @par Preconditions
592  
        None of the character buffers referenced
592  
        None of the character buffers referenced
593  
        by the list may overlap the character
593  
        by the list may overlap the character
594  
        buffer of the underlying url, or else
594  
        buffer of the underlying url, or else
595  
        the behavior is undefined.
595  
        the behavior is undefined.
596  

596  

597  
        @par Complexity
597  
        @par Complexity
598  
        Linear in `init.size() + this->url().encoded_resouce().size()`.
598  
        Linear in `init.size() + this->url().encoded_resouce().size()`.
599  

599  

600  
        @par Exception Safety
600  
        @par Exception Safety
601  
        Strong guarantee.
601  
        Strong guarantee.
602  
        Calls to allocate may throw.
602  
        Calls to allocate may throw.
603  

603  

604  
        @return An iterator to the first
604  
        @return An iterator to the first
605  
        segment inserted, or one past `to` if
605  
        segment inserted, or one past `to` if
606  
        `init.size() == 0`.
606  
        `init.size() == 0`.
607  

607  

608  
        @param from The beginning of the range of segments to replace.
608  
        @param from The beginning of the range of segments to replace.
609  
        @param to The end of the range of segments to replace.
609  
        @param to The end of the range of segments to replace.
610  

610  

611  
        @param init The list of segments to assign.
611  
        @param init The list of segments to assign.
612  
    */
612  
    */
613  
    iterator
613  
    iterator
614  
    replace(
614  
    replace(
615  
        iterator from,
615  
        iterator from,
616  
        iterator to,
616  
        iterator to,
617  
        std::initializer_list<
617  
        std::initializer_list<
618  
            core::string_view> init);
618  
            core::string_view> init);
619  

619  

620  
    /** Replace segments
620  
    /** Replace segments
621  

621  

622  
        This function replaces a range of
622  
        This function replaces a range of
623  
        segments with annother range of segments.
623  
        segments with annother range of segments.
624  
        Reserved characters in the new range are
624  
        Reserved characters in the new range are
625  
        automatically escaped.
625  
        automatically escaped.
626  

626  

627  
        <br>
627  
        <br>
628  
        All iterators that are equal to
628  
        All iterators that are equal to
629  
        `from` or come after are invalidated.
629  
        `from` or come after are invalidated.
630  

630  

631  
        @par Preconditions
631  
        @par Preconditions
632  
        None of the character buffers referenced
632  
        None of the character buffers referenced
633  
        by the new range may overlap the character
633  
        by the new range may overlap the character
634  
        buffer of the underlying url, or else
634  
        buffer of the underlying url, or else
635  
        the behavior is undefined.
635  
        the behavior is undefined.
636  

636  

637  
        @par Complexity
637  
        @par Complexity
638  
        Linear in `std::distance( first, last ) + this->url().encoded_resouce().size()`.
638  
        Linear in `std::distance( first, last ) + this->url().encoded_resouce().size()`.
639  

639  

640  
        @par Exception Safety
640  
        @par Exception Safety
641  
        Strong guarantee.
641  
        Strong guarantee.
642  
        Calls to allocate may throw.
642  
        Calls to allocate may throw.
643  

643  

644  
        @return An iterator to the first
644  
        @return An iterator to the first
645  
        segment inserted, or one past `to` if
645  
        segment inserted, or one past `to` if
646  
        `init.size() == 0`.
646  
        `init.size() == 0`.
647  

647  

648  
        @param from The beginning of the range of segments to replace.
648  
        @param from The beginning of the range of segments to replace.
649  
        @param to The end 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.
650  
        @param first The beginning of the range of segments to assign.
651  
        @param last The end of the range of segments to assign.
651  
        @param last The end of the range of segments to assign.
652  
    */
652  
    */
653  
    template<class FwdIt>
653  
    template<class FwdIt>
654  
    iterator
654  
    iterator
655  
    replace(
655  
    replace(
656  
        iterator from,
656  
        iterator from,
657  
        iterator to,
657  
        iterator to,
658  
        FwdIt first,
658  
        FwdIt first,
659  
        FwdIt last);
659  
        FwdIt last);
660  

660  

661  
    /** Append a segment
661  
    /** Append a segment
662  

662  

663  
        This function appends a segment to
663  
        This function appends a segment to
664  
        the end of the path.
664  
        the end of the path.
665  
        Reserved characters in the string are
665  
        Reserved characters in the string are
666  
        automatically escaped.
666  
        automatically escaped.
667  

667  

668  
        <br>
668  
        <br>
669  
        All end iterators are invalidated.
669  
        All end iterators are invalidated.
670  

670  

671  
        @par Postconditions
671  
        @par Postconditions
672  
        @code
672  
        @code
673  
        this->back() == s
673  
        this->back() == s
674  
        @endcode
674  
        @endcode
675  

675  

676  
        @par Exception Safety
676  
        @par Exception Safety
677  
        Strong guarantee.
677  
        Strong guarantee.
678  
        Calls to allocate may throw.
678  
        Calls to allocate may throw.
679  

679  

680  
        @param s The segment to append.
680  
        @param s The segment to append.
681  
    */
681  
    */
682  
    void
682  
    void
683  
    push_back(
683  
    push_back(
684  
        core::string_view s);
684  
        core::string_view s);
685  

685  

686  
    /** Remove the last segment
686  
    /** Remove the last segment
687  

687  

688  
        This function removes the last segment
688  
        This function removes the last segment
689  
        from the container.
689  
        from the container.
690  

690  

691  
        <br>
691  
        <br>
692  
        Iterators to the last segment as well
692  
        Iterators to the last segment as well
693  
        as all end iterators are invalidated.
693  
        as all end iterators are invalidated.
694  

694  

695  
        @par Preconditions
695  
        @par Preconditions
696  
        @code
696  
        @code
697  
        not this->empty()
697  
        not this->empty()
698  
        @endcode
698  
        @endcode
699  

699  

700  
        @par Exception Safety
700  
        @par Exception Safety
701  
        Throws nothing.
701  
        Throws nothing.
702  
    */
702  
    */
703  
    void
703  
    void
704  
    pop_back() noexcept;
704  
    pop_back() noexcept;
705  

705  

706  
private:
706  
private:
707  
    template<class FwdIt>
707  
    template<class FwdIt>
708  
    iterator
708  
    iterator
709  
    insert(
709  
    insert(
710  
        iterator before,
710  
        iterator before,
711  
        FwdIt first,
711  
        FwdIt first,
712  
        FwdIt last,
712  
        FwdIt last,
713  
        std::input_iterator_tag) = delete;
713  
        std::input_iterator_tag) = delete;
714  

714  

715  
    template<class FwdIt>
715  
    template<class FwdIt>
716  
    iterator
716  
    iterator
717  
    insert(
717  
    insert(
718  
        iterator before,
718  
        iterator before,
719  
        FwdIt first,
719  
        FwdIt first,
720  
        FwdIt last,
720  
        FwdIt last,
721  
        std::forward_iterator_tag);
721  
        std::forward_iterator_tag);
722  
};
722  
};
723  

723  

724  
} // urls
724  
} // urls
725  
} // boost
725  
} // boost
726  

726  

727  
// This include is at the bottom of
727  
// This include is at the bottom of
728  
// url_base.hpp because of a circular dependency
728  
// url_base.hpp because of a circular dependency
729  
//
729  
//
730  
// #include <boost/url/impl/segments_ref.hpp>
730  
// #include <boost/url/impl/segments_ref.hpp>
731  

731  

732  
//------------------------------------------------
732  
//------------------------------------------------
733  
//
733  
//
734  
// std::ranges::enable_borrowed_range
734  
// std::ranges::enable_borrowed_range
735  
//
735  
//
736  
//------------------------------------------------
736  
//------------------------------------------------
737  

737  

738  
#ifdef BOOST_URL_HAS_CONCEPTS
738  
#ifdef BOOST_URL_HAS_CONCEPTS
739  
#include <ranges>
739  
#include <ranges>
740  
namespace std::ranges {
740  
namespace std::ranges {
741  
    template<>
741  
    template<>
742  
    inline constexpr bool
742  
    inline constexpr bool
743  
        enable_borrowed_range<
743  
        enable_borrowed_range<
744  
            boost::urls::segments_ref> = true;
744  
            boost::urls::segments_ref> = true;
745  
} // std::ranges
745  
} // std::ranges
746  
#endif
746  
#endif
747  

747  

748  
#endif
748  
#endif