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_ENCODED_BASE_HPP
11  
#ifndef BOOST_URL_SEGMENTS_ENCODED_BASE_HPP
12  
#define BOOST_URL_SEGMENTS_ENCODED_BASE_HPP
12  
#define BOOST_URL_SEGMENTS_ENCODED_BASE_HPP
13  

13  

14  
#include <boost/url/detail/config.hpp>
14  
#include <boost/url/detail/config.hpp>
15  
#include <boost/url/ignore_case.hpp>
15  
#include <boost/url/ignore_case.hpp>
16  
#include <boost/url/pct_string_view.hpp>
16  
#include <boost/url/pct_string_view.hpp>
17  
#include <boost/url/detail/url_impl.hpp>
17  
#include <boost/url/detail/url_impl.hpp>
18  
#include <iosfwd>
18  
#include <iosfwd>
19  

19  

20  
namespace boost {
20  
namespace boost {
21  
namespace urls {
21  
namespace urls {
22  

22  

23  
/** Percent-encoded path segment helper base
23  
/** Percent-encoded path segment helper base
24  

24  

25  
    Implements the shared encoded-segment
25  
    Implements the shared encoded-segment
26  
    algorithms reused by @ref segments_encoded_view
26  
    algorithms reused by @ref segments_encoded_view
27  
    and @ref segments_encoded_ref. It is not
27  
    and @ref segments_encoded_ref. It is not
28  
    intended to be instantiated directly; use
28  
    intended to be instantiated directly; use
29  
    one of those concrete containers instead.
29  
    one of those concrete containers instead.
30  

30  

31  
    @par Containers
31  
    @par Containers
32  
    @li @ref segments_ref
32  
    @li @ref segments_ref
33  
    @li @ref segments_view
33  
    @li @ref segments_view
34  
    @li @ref segments_encoded_ref
34  
    @li @ref segments_encoded_ref
35  
    @li @ref segments_encoded_view
35  
    @li @ref segments_encoded_view
36  
*/
36  
*/
37 -
class segments_encoded_base
37 +
class BOOST_URL_DECL segments_encoded_base
38  
{
38  
{
39  
    detail::path_ref ref_;
39  
    detail::path_ref ref_;
40  

40  

41  
    friend class url_view_base;
41  
    friend class url_view_base;
42  
    friend class segments_encoded_ref;
42  
    friend class segments_encoded_ref;
43  
    friend class segments_encoded_view;
43  
    friend class segments_encoded_view;
44  

44  

45  
    segments_encoded_base(
45  
    segments_encoded_base(
46  
        detail::path_ref const& ref) noexcept;
46  
        detail::path_ref const& ref) noexcept;
47  
    segments_encoded_base() = default;
47  
    segments_encoded_base() = default;
48  
    segments_encoded_base(
48  
    segments_encoded_base(
49  
        segments_encoded_base const&) = default;
49  
        segments_encoded_base const&) = default;
50  
    segments_encoded_base& operator=(
50  
    segments_encoded_base& operator=(
51  
        segments_encoded_base const&) = default;
51  
        segments_encoded_base const&) = default;
52  

52  

53  
public:
53  
public:
54  
    /** A Bidirectional iterator to a path segment
54  
    /** A Bidirectional iterator to a path segment
55  

55  

56  
        Objects of this type allow iteration
56  
        Objects of this type allow iteration
57  
        through the segments in the path.
57  
        through the segments in the path.
58  
        Strings returned by iterators may
58  
        Strings returned by iterators may
59  
        contain percent escapes.
59  
        contain percent escapes.
60  
        The values returned are read-only;
60  
        The values returned are read-only;
61  
        changes to segments must be made
61  
        changes to segments must be made
62  
        through the container instead, if the
62  
        through the container instead, if the
63  
        container supports modification.
63  
        container supports modification.
64  

64  

65  
        <br>
65  
        <br>
66  

66  

67  
        The strings produced when iterators
67  
        The strings produced when iterators
68  
        are dereferenced refer to the underlying
68  
        are dereferenced refer to the underlying
69  
        character buffer.
69  
        character buffer.
70  
        Ownership is not transferred; the caller
70  
        Ownership is not transferred; the caller
71  
        is responsible for ensuring that the
71  
        is responsible for ensuring that the
72  
        lifetime of the buffer extends until
72  
        lifetime of the buffer extends until
73  
        it is no longer referenced by any
73  
        it is no longer referenced by any
74  
        container or iterator.
74  
        container or iterator.
75  
    */
75  
    */
76  
    class iterator;
76  
    class iterator;
77  

77  

78  
    /// @copydoc iterator
78  
    /// @copydoc iterator
79  
    using const_iterator = iterator;
79  
    using const_iterator = iterator;
80  

80  

81  
    /** The value type
81  
    /** The value type
82  

82  

83  
        Values of this type represent a segment
83  
        Values of this type represent a segment
84  
        where unique ownership is retained by
84  
        where unique ownership is retained by
85  
        making a copy.
85  
        making a copy.
86  

86  

87  
        @par Example
87  
        @par Example
88  
        @code
88  
        @code
89  
        segments_encoded_base::value_type ps( url_view( "/path/to/file.txt" ).encoded_segments().back() );
89  
        segments_encoded_base::value_type ps( url_view( "/path/to/file.txt" ).encoded_segments().back() );
90  
        @endcode
90  
        @endcode
91  
    */
91  
    */
92  
    using value_type = std::string;
92  
    using value_type = std::string;
93  

93  

94  
    /** The reference type
94  
    /** The reference type
95  

95  

96  
        This is the type of value returned when
96  
        This is the type of value returned when
97  
        iterators of the view are dereferenced.
97  
        iterators of the view are dereferenced.
98  
    */
98  
    */
99  
    using reference = pct_string_view;
99  
    using reference = pct_string_view;
100  

100  

101  
    /// @copydoc reference
101  
    /// @copydoc reference
102  
    using const_reference = pct_string_view;
102  
    using const_reference = pct_string_view;
103  

103  

104  
    /** An unsigned integer type used to represent size.
104  
    /** An unsigned integer type used to represent size.
105  
    */
105  
    */
106  
    using size_type = std::size_t;
106  
    using size_type = std::size_t;
107  

107  

108  
    /** A signed integer type used to represent differences.
108  
    /** A signed integer type used to represent differences.
109  
    */
109  
    */
110  
    using difference_type = std::ptrdiff_t;
110  
    using difference_type = std::ptrdiff_t;
111  

111  

112  
    //--------------------------------------------
112  
    //--------------------------------------------
113  
    //
113  
    //
114  
    // Observers
114  
    // Observers
115  
    //
115  
    //
116  
    //--------------------------------------------
116  
    //--------------------------------------------
117  

117  

118  
    /** Return the maximum number of characters possible
118  
    /** Return the maximum number of characters possible
119  

119  

120  
        This represents the largest number of
120  
        This represents the largest number of
121  
        characters that are possible in a path,
121  
        characters that are possible in a path,
122  
        not including any null terminator.
122  
        not including any null terminator.
123  

123  

124  
        @par Exception Safety
124  
        @par Exception Safety
125  
        Throws nothing.
125  
        Throws nothing.
126  

126  

127  
        @return The maximum number of characters possible.
127  
        @return The maximum number of characters possible.
128  
    */
128  
    */
129  
    static
129  
    static
130  
    constexpr
130  
    constexpr
131  
    std::size_t
131  
    std::size_t
132  
    max_size() noexcept
132  
    max_size() noexcept
133  
    {
133  
    {
134  
        return BOOST_URL_MAX_SIZE;
134  
        return BOOST_URL_MAX_SIZE;
135  
    }
135  
    }
136  

136  

137  
    /** Return the referenced character buffer.
137  
    /** Return the referenced character buffer.
138  

138  

139  
        This function returns the character
139  
        This function returns the character
140  
        buffer referenced by the view.
140  
        buffer referenced by the view.
141  
        The returned string may contain
141  
        The returned string may contain
142  
        percent escapes.
142  
        percent escapes.
143  

143  

144  
        @par Example
144  
        @par Example
145  
        @code
145  
        @code
146  
        assert( url_view( "/path/to/file.txt" ).encoded_segments().buffer() == "/path/to/file.txt" );
146  
        assert( url_view( "/path/to/file.txt" ).encoded_segments().buffer() == "/path/to/file.txt" );
147  
        @endcode
147  
        @endcode
148  

148  

149  
        @par Complexity
149  
        @par Complexity
150  
        Constant.
150  
        Constant.
151  

151  

152  
        @par Exception Safety
152  
        @par Exception Safety
153  
        Throws nothing.
153  
        Throws nothing.
154  

154  

155  
        @return A string view of the buffer.
155  
        @return A string view of the buffer.
156 -
    BOOST_URL_DECL
 
157  
    */
156  
    */
158  
    pct_string_view
157  
    pct_string_view
159  
    buffer() const noexcept;
158  
    buffer() const noexcept;
160  

159  

161  
    /** Returns true if this references an absolute path.
160  
    /** Returns true if this references an absolute path.
162  

161  

163  
        Absolute paths always start with a
162  
        Absolute paths always start with a
164  
        forward slash ('/').
163  
        forward slash ('/').
165  

164  

166  
        @par Example
165  
        @par Example
167  
        @code
166  
        @code
168  
        assert( url_view( "/path/to/file.txt" ).encoded_segments().is_absolute() == true );
167  
        assert( url_view( "/path/to/file.txt" ).encoded_segments().is_absolute() == true );
169  
        @endcode
168  
        @endcode
170  

169  

171  
        @par Complexity
170  
        @par Complexity
172  
        Constant.
171  
        Constant.
173  

172  

174  
        @par Exception Safety
173  
        @par Exception Safety
175  
        Throws nothing.
174  
        Throws nothing.
176  

175  

177  
        @return `true` if the path is absolute, otherwise `false`.
176  
        @return `true` if the path is absolute, otherwise `false`.
178 -
    BOOST_URL_DECL
 
179  
    */
177  
    */
180  
    bool
178  
    bool
181  
    is_absolute() const noexcept;
179  
    is_absolute() const noexcept;
182  

180  

183  
    /** Return true if there are no segments
181  
    /** Return true if there are no segments
184  

182  

185  
        @par Example
183  
        @par Example
186  
        @code
184  
        @code
187  
        assert( ! url_view( "/index.htm" ).encoded_segments().empty() );
185  
        assert( ! url_view( "/index.htm" ).encoded_segments().empty() );
188  
        @endcode
186  
        @endcode
189  

187  

190  
        @par Complexity
188  
        @par Complexity
191  
        Constant.
189  
        Constant.
192  

190  

193  
        @par Exception Safety
191  
        @par Exception Safety
194  
        Throws nothing.
192  
        Throws nothing.
195  

193  

196  
        @return `true` if there are no segments, otherwise `false`.
194  
        @return `true` if there are no segments, otherwise `false`.
197 -
    BOOST_URL_DECL
 
198  
    */
195  
    */
199  
    bool
196  
    bool
200  
    empty() const noexcept;
197  
    empty() const noexcept;
201  

198  

202  
    /** Return the number of segments
199  
    /** Return the number of segments
203  
    
200  
    
204  
        @par Example
201  
        @par Example
205  
        @code
202  
        @code
206  
        assert( url_view( "/path/to/file.txt" ).encoded_segments().size() == 3 );
203  
        assert( url_view( "/path/to/file.txt" ).encoded_segments().size() == 3 );
207  
        @endcode
204  
        @endcode
208  

205  

209  
        @par Complexity
206  
        @par Complexity
210  
        Constant.
207  
        Constant.
211  

208  

212  
        @par Exception Safety
209  
        @par Exception Safety
213  
        Throws nothing.
210  
        Throws nothing.
214  

211  

215  
        @return The number of segments.
212  
        @return The number of segments.
216 -
    BOOST_URL_DECL
 
217  
    */
213  
    */
218  
    std::size_t
214  
    std::size_t
219  
    size() const noexcept;
215  
    size() const noexcept;
220  

216  

221  
    /** Return the first segment
217  
    /** Return the first segment
222  

218  

223  
        This function returns a string with the
219  
        This function returns a string with the
224  
        first segment of the path without any
220  
        first segment of the path without any
225  
        leading or trailing '/' separators.
221  
        leading or trailing '/' separators.
226  
        The returned string may contain
222  
        The returned string may contain
227  
        percent escapes.
223  
        percent escapes.
228  

224  

229  
        @par Preconditions
225  
        @par Preconditions
230  
        @code
226  
        @code
231  
        this->empty() == false
227  
        this->empty() == false
232  
        @endcode
228  
        @endcode
233  

229  

234  
        @par Effects
230  
        @par Effects
235  
        @code
231  
        @code
236  
        return *begin();
232  
        return *begin();
237  
        @endcode
233  
        @endcode
238  

234  

239  
        @par Example
235  
        @par Example
240  
        @code
236  
        @code
241  
        assert( url_view( "/path/to/file.txt" ).encoded_segments().front() == "path" );
237  
        assert( url_view( "/path/to/file.txt" ).encoded_segments().front() == "path" );
242  
        @endcode
238  
        @endcode
243  

239  

244  
        @par Complexity
240  
        @par Complexity
245  
        Constant.
241  
        Constant.
246  

242  

247  
        @par Exception Safety
243  
        @par Exception Safety
248  
        Throws nothing.
244  
        Throws nothing.
249  

245  

250  
        @return The first segment.
246  
        @return The first segment.
251  
    */
247  
    */
252  
    pct_string_view
248  
    pct_string_view
253  
    front() const noexcept;
249  
    front() const noexcept;
254  

250  

255  
    /** Return the last segment
251  
    /** Return the last segment
256  

252  

257  
        This function returns a string with the
253  
        This function returns a string with the
258  
        last segment of the path without any
254  
        last segment of the path without any
259  
        leading or trailing '/' separators.
255  
        leading or trailing '/' separators.
260  
        The returned string may contain
256  
        The returned string may contain
261  
        percent escapes.
257  
        percent escapes.
262  

258  

263  
        @par Preconditions
259  
        @par Preconditions
264  
        @code
260  
        @code
265  
        this->empty() == false
261  
        this->empty() == false
266  
        @endcode
262  
        @endcode
267  

263  

268  
        @par Example
264  
        @par Example
269  
        @code
265  
        @code
270  
        assert( url_view( "/path/to/file.txt" ).encoded_segments().back() == "file.txt" );
266  
        assert( url_view( "/path/to/file.txt" ).encoded_segments().back() == "file.txt" );
271  
        @endcode
267  
        @endcode
272  

268  

273  
        @par Preconditions
269  
        @par Preconditions
274  
        @code
270  
        @code
275  
        this->empty() == false
271  
        this->empty() == false
276  
        @endcode
272  
        @endcode
277  

273  

278  
        @par Effects
274  
        @par Effects
279  
        @code
275  
        @code
280  
        return *--end();
276  
        return *--end();
281  
        @endcode
277  
        @endcode
282  

278  

283  
        @par Complexity
279  
        @par Complexity
284  
        Constant.
280  
        Constant.
285  

281  

286  
        @par Exception Safety
282  
        @par Exception Safety
287  
        Throws nothing.
283  
        Throws nothing.
288  

284  

289  
        @return The last segment.
285  
        @return The last segment.
290  
    */
286  
    */
291  
    pct_string_view
287  
    pct_string_view
292  
    back() const noexcept;
288  
    back() const noexcept;
293  

289  

294  
    /** Return an iterator to the beginning
290  
    /** Return an iterator to the beginning
295  

291  

296  
        @par Complexity
292  
        @par Complexity
297  
        Linear in `this->front().size()` or
293  
        Linear in `this->front().size()` or
298  
        constant if `this->empty()`.
294  
        constant if `this->empty()`.
299  

295  

300  
        @par Exception Safety
296  
        @par Exception Safety
301  
        Throws nothing.
297  
        Throws nothing.
302  

298  

303  
        @return An iterator to the first segment.
299  
        @return An iterator to the first segment.
304 -
    BOOST_URL_DECL
 
305  
    */
300  
    */
306  
    iterator
301  
    iterator
307  
    begin() const noexcept;
302  
    begin() const noexcept;
308  

303  

309  
    /** Return an iterator to the end
304  
    /** Return an iterator to the end
310  

305  

311  
        @par Complexity
306  
        @par Complexity
312  
        Constant.
307  
        Constant.
313  

308  

314  
        @par Exception Safety
309  
        @par Exception Safety
315  
        Throws nothing.
310  
        Throws nothing.
316  

311  

317  
        @return An iterator to one past the last segment.
312  
        @return An iterator to one past the last segment.
318 -
    BOOST_URL_DECL
 
319  
    */
313  
    */
320  
    iterator
314  
    iterator
321  
    end() const noexcept;
315  
    end() const noexcept;
322  
};
316  
};
323  

317  

324  
//------------------------------------------------
318  
//------------------------------------------------
325  

319  

326  
/** Format to an output stream
320  
/** Format to an output stream
327  

321  

328  
    Any percent-escapes are emitted as-is;
322  
    Any percent-escapes are emitted as-is;
329  
    no decoding is performed.
323  
    no decoding is performed.
330  

324  

331  
    @par Complexity
325  
    @par Complexity
332  
    Linear in `ps.buffer().size()`.
326  
    Linear in `ps.buffer().size()`.
333  

327  

334  
    @par Effects
328  
    @par Effects
335  
    @code
329  
    @code
336  
    return os << ps.buffer();
330  
    return os << ps.buffer();
337  
    @endcode
331  
    @endcode
338  

332  

339  
    @param os The output stream to write to.
333  
    @param os The output stream to write to.
340  
    @param ps The object to format.
334  
    @param ps The object to format.
341  
    @return A reference to the output stream.
335  
    @return A reference to the output stream.
342  
*/
336  
*/
343  
BOOST_URL_DECL
337  
BOOST_URL_DECL
344  
std::ostream&
338  
std::ostream&
345  
operator<<(
339  
operator<<(
346  
    std::ostream& os,
340  
    std::ostream& os,
347  
    segments_encoded_base const& ps);
341  
    segments_encoded_base const& ps);
348  

342  

349  
} // urls
343  
} // urls
350  
} // boost
344  
} // boost
351  

345  

352  
#include <boost/url/impl/segments_encoded_base.hpp>
346  
#include <boost/url/impl/segments_encoded_base.hpp>
353  

347  

354  
#endif
348  
#endif