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 BOOST_SYMBOL_VISIBLE segments_encoded_base
37  
class BOOST_SYMBOL_VISIBLE 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  
    */
156  
    */
157  
    pct_string_view
157  
    pct_string_view
158  
    buffer() const noexcept;
158  
    buffer() const noexcept;
159  

159  

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

161  

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

164  

165  
        @par Example
165  
        @par Example
166  
        @code
166  
        @code
167  
        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 );
168  
        @endcode
168  
        @endcode
169  

169  

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

172  

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

175  

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

180  

181  
    /** Return true if there are no segments
181  
    /** Return true if there are no segments
182  

182  

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

187  

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

190  

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

193  

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

198  

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

205  

206  
        @par Complexity
206  
        @par Complexity
207  
        Constant.
207  
        Constant.
208  

208  

209  
        @par Exception Safety
209  
        @par Exception Safety
210  
        Throws nothing.
210  
        Throws nothing.
211  

211  

212  
        @return The number of segments.
212  
        @return The number of segments.
213  
    */
213  
    */
214  
    std::size_t
214  
    std::size_t
215  
    size() const noexcept;
215  
    size() const noexcept;
216  

216  

217  
    /** Return the first segment
217  
    /** Return the first segment
218  

218  

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

224  

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

229  

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

234  

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

239  

240  
        @par Complexity
240  
        @par Complexity
241  
        Constant.
241  
        Constant.
242  

242  

243  
        @par Exception Safety
243  
        @par Exception Safety
244  
        Throws nothing.
244  
        Throws nothing.
245  

245  

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

250  

251  
    /** Return the last segment
251  
    /** Return the last segment
252  

252  

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

258  

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

263  

264  
        @par Example
264  
        @par Example
265  
        @code
265  
        @code
266  
        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" );
267  
        @endcode
267  
        @endcode
268  

268  

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

273  

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

278  

279  
        @par Complexity
279  
        @par Complexity
280  
        Constant.
280  
        Constant.
281  

281  

282  
        @par Exception Safety
282  
        @par Exception Safety
283  
        Throws nothing.
283  
        Throws nothing.
284  

284  

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

289  

290  
    /** Return an iterator to the beginning
290  
    /** Return an iterator to the beginning
291  

291  

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

295  

296  
        @par Exception Safety
296  
        @par Exception Safety
297  
        Throws nothing.
297  
        Throws nothing.
298  

298  

299  
        @return An iterator to the first segment.
299  
        @return An iterator to the first segment.
300  
    */
300  
    */
301  
    iterator
301  
    iterator
302  
    begin() const noexcept;
302  
    begin() const noexcept;
303  

303  

304  
    /** Return an iterator to the end
304  
    /** Return an iterator to the end
305  

305  

306  
        @par Complexity
306  
        @par Complexity
307  
        Constant.
307  
        Constant.
308  

308  

309  
        @par Exception Safety
309  
        @par Exception Safety
310  
        Throws nothing.
310  
        Throws nothing.
311  

311  

312  
        @return An iterator to one past the last segment.
312  
        @return An iterator to one past the last segment.
313  
    */
313  
    */
314  
    iterator
314  
    iterator
315  
    end() const noexcept;
315  
    end() const noexcept;
316  
};
316  
};
317  

317  

318  
//------------------------------------------------
318  
//------------------------------------------------
319  

319  

320  
/** Format to an output stream
320  
/** Format to an output stream
321  

321  

322  
    Any percent-escapes are emitted as-is;
322  
    Any percent-escapes are emitted as-is;
323  
    no decoding is performed.
323  
    no decoding is performed.
324  

324  

325  
    @par Complexity
325  
    @par Complexity
326  
    Linear in `ps.buffer().size()`.
326  
    Linear in `ps.buffer().size()`.
327  

327  

328  
    @par Effects
328  
    @par Effects
329  
    @code
329  
    @code
330  
    return os << ps.buffer();
330  
    return os << ps.buffer();
331  
    @endcode
331  
    @endcode
332  

332  

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

341  

342  
} // urls
342  
} // urls
343  
} // boost
343  
} // boost
344  

344  

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

346  

347  
#endif
347  
#endif