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_BASE_HPP
11  
#ifndef BOOST_URL_SEGMENTS_BASE_HPP
12  
#define BOOST_URL_SEGMENTS_BASE_HPP
12  
#define BOOST_URL_SEGMENTS_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/detail/url_impl.hpp>
16  
#include <boost/url/detail/url_impl.hpp>
17  
#include <iosfwd>
17  
#include <iosfwd>
18  
#include <string>
18  
#include <string>
19  

19  

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

22  

23  
/** Decoded path segment helper base
23  
/** Decoded path segment helper base
24  

24  

25  
    Provides the shared decoded path-segment
25  
    Provides the shared decoded path-segment
26  
    algorithms (iteration, lookup, comparison)
26  
    algorithms (iteration, lookup, comparison)
27  
    used by @ref segments_view and
27  
    used by @ref segments_view and
28  
    @ref segments_ref. This base cannot be
28  
    @ref segments_ref. This base cannot be
29  
    instantiated directly; instead, use one of
29  
    instantiated directly; instead, use one of
30  
    the concrete containers below.
30  
    the concrete containers below.
31  

31  

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

41  

42  
    friend class url_view_base;
42  
    friend class url_view_base;
43  
    friend class segments_ref;
43  
    friend class segments_ref;
44  
    friend class segments_view;
44  
    friend class segments_view;
45  

45  

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

53  

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

56  

57  
        Objects of this type allow iteration
57  
        Objects of this type allow iteration
58  
        through the segments in the path.
58  
        through the segments in the path.
59  
        Any percent-escapes in returned strings
59  
        Any percent-escapes in returned strings
60  
        are decoded first.
60  
        are decoded first.
61  
        The values returned are read-only;
61  
        The values returned are read-only;
62  
        changes to segments must be made
62  
        changes to segments must be made
63  
        through the container instead, if the
63  
        through the container instead, if the
64  
        container supports modification.
64  
        container supports modification.
65  

65  

66  
        <br>
66  
        <br>
67  

67  

68  
        The strings produced when iterators are
68  
        The strings produced when iterators are
69  
        dereferenced belong to the iterator and
69  
        dereferenced belong to the iterator and
70  
        become invalidated when that particular
70  
        become invalidated when that particular
71  
        iterator is incremented, decremented,
71  
        iterator is incremented, decremented,
72  
        or destroyed.
72  
        or destroyed.
73  
    */
73  
    */
74  
    class iterator;
74  
    class iterator;
75  

75  

76  
    /// @copydoc iterator
76  
    /// @copydoc iterator
77  
    using const_iterator = iterator;
77  
    using const_iterator = iterator;
78  

78  

79  
    /** The value type
79  
    /** The value type
80  

80  

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

84  

85  
        @par Example
85  
        @par Example
86  
        @code
86  
        @code
87  
        segments_base::value_type ps( url_view( "/path/to/file.txt" ).segments().back() );
87  
        segments_base::value_type ps( url_view( "/path/to/file.txt" ).segments().back() );
88  
        @endcode
88  
        @endcode
89  
    */
89  
    */
90  
    using value_type = std::string;
90  
    using value_type = std::string;
91  

91  

92  
    /** The reference type
92  
    /** The reference type
93  

93  

94  
        This is the type of value returned when
94  
        This is the type of value returned when
95  
        iterators of the view are dereferenced.
95  
        iterators of the view are dereferenced.
96  
    */
96  
    */
97  
    using reference = std::string;
97  
    using reference = std::string;
98  

98  

99  
    /// @copydoc reference
99  
    /// @copydoc reference
100  
    using const_reference = std::string;
100  
    using const_reference = std::string;
101  

101  

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

105  

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

109  

110  
    //--------------------------------------------
110  
    //--------------------------------------------
111  
    //
111  
    //
112  
    // Observers
112  
    // Observers
113  
    //
113  
    //
114  
    //--------------------------------------------
114  
    //--------------------------------------------
115  

115  

116  
    /** Return the maximum number of characters possible
116  
    /** Return the maximum number of characters possible
117  

117  

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

121  

122  
        @par Exception Safety
122  
        @par Exception Safety
123  
        Throws nothing.
123  
        Throws nothing.
124  

124  

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

134  

135  
    /** Return the referenced character buffer.
135  
    /** Return the referenced character buffer.
136  

136  

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

141  

142  
        @par Example
142  
        @par Example
143  
        @code
143  
        @code
144  
        assert( url_view( "/path/to/file.txt" ).segments().buffer() == "/path/to/file.txt" );
144  
        assert( url_view( "/path/to/file.txt" ).segments().buffer() == "/path/to/file.txt" );
145  
        @endcode
145  
        @endcode
146  

146  

147  
        @par Complexity
147  
        @par Complexity
148  
        Constant.
148  
        Constant.
149  

149  

150  
        @par Exception Safety
150  
        @par Exception Safety
151  
        Throws nothing.
151  
        Throws nothing.
152  

152  

153  
        @return A string containing the path.
153  
        @return A string containing the path.
154 -
    BOOST_URL_DECL
 
155  
    */
154  
    */
156  
    pct_string_view
155  
    pct_string_view
157  
    buffer() const noexcept;
156  
    buffer() const noexcept;
158  

157  

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

159  

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

162  

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

167  

169  
        @par Complexity
168  
        @par Complexity
170  
        Constant.
169  
        Constant.
171  

170  

172  
        @par Exception Safety
171  
        @par Exception Safety
173  
        Throws nothing.
172  
        Throws nothing.
174  

173  

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

178  

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

180  

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

185  

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

188  

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

191  

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

196  

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

203  

207  
        @par Complexity
204  
        @par Complexity
208  
        Constant.
205  
        Constant.
209  

206  

210  
        @par Exception Safety
207  
        @par Exception Safety
211  
        Throws nothing.
208  
        Throws nothing.
212  

209  

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

214  

219  
    /** Return the first segment
215  
    /** Return the first segment
220  

216  

221  
        This function returns a string with the
217  
        This function returns a string with the
222  
        first segment of the path without any
218  
        first segment of the path without any
223  
        leading or trailing '/' separators.
219  
        leading or trailing '/' separators.
224  
        Any percent-escapes in the string are
220  
        Any percent-escapes in the string are
225  
        decoded first.
221  
        decoded first.
226  

222  

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

227  

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

232  

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

237  

242  
        @par Complexity
238  
        @par Complexity
243  
        Linear in `this->front().size()`.
239  
        Linear in `this->front().size()`.
244  

240  

245  
        @par Exception Safety
241  
        @par Exception Safety
246  
        Calls to allocate may throw.
242  
        Calls to allocate may throw.
247  

243  

248  
        @return The first segment.
244  
        @return The first segment.
249  
    */
245  
    */
250  
    std::string
246  
    std::string
251  
    front() const noexcept;
247  
    front() const noexcept;
252  

248  

253  
    /** Return the last segment
249  
    /** Return the last segment
254  

250  

255  
        @par Preconditions
251  
        @par Preconditions
256  
        @code
252  
        @code
257  
        this->empty() == false
253  
        this->empty() == false
258  
        @endcode
254  
        @endcode
259  

255  

260  
        @par Example
256  
        @par Example
261  
        @code
257  
        @code
262  
        assert( url_view( "/path/to/file.txt" ).segments().back() == "file.txt" );
258  
        assert( url_view( "/path/to/file.txt" ).segments().back() == "file.txt" );
263  
        @endcode
259  
        @endcode
264  

260  

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

265  

270  
        @par Effects
266  
        @par Effects
271  
        @code
267  
        @code
272  
        return *--end();
268  
        return *--end();
273  
        @endcode
269  
        @endcode
274  

270  

275  
        @par Complexity
271  
        @par Complexity
276  
        Linear in `this->back().size()`.
272  
        Linear in `this->back().size()`.
277  

273  

278  
        @par Exception Safety
274  
        @par Exception Safety
279  
        Calls to allocate may throw.
275  
        Calls to allocate may throw.
280  

276  

281  
        @return The last segment.
277  
        @return The last segment.
282  
    */
278  
    */
283  
    std::string
279  
    std::string
284  
    back() const noexcept;
280  
    back() const noexcept;
285  

281  

286  
    /** Return an iterator to the beginning
282  
    /** Return an iterator to the beginning
287  

283  

288  
        @par Complexity
284  
        @par Complexity
289  
        Linear in `this->front().size()` or
285  
        Linear in `this->front().size()` or
290  
        constant if `this->empty()`.
286  
        constant if `this->empty()`.
291  

287  

292  
        @par Exception Safety
288  
        @par Exception Safety
293  
        Throws nothing.
289  
        Throws nothing.
294  

290  

295  
        @return An iterator to the first segment.
291  
        @return An iterator to the first segment.
296 -
    BOOST_URL_DECL
 
297  
    */
292  
    */
298  
    iterator
293  
    iterator
299  
    begin() const noexcept;
294  
    begin() const noexcept;
300  

295  

301  
    /** Return an iterator to the end
296  
    /** Return an iterator to the end
302  

297  

303  
        @par Complexity
298  
        @par Complexity
304  
        Constant.
299  
        Constant.
305  

300  

306  
        @par Exception Safety
301  
        @par Exception Safety
307  
        Throws nothing.
302  
        Throws nothing.
308  

303  

309  
        @return An iterator to one past the last segment.
304  
        @return An iterator to one past the last segment.
310 -
    BOOST_URL_DECL
 
311  
    */
305  
    */
312  
    iterator
306  
    iterator
313  
    end() const noexcept;
307  
    end() const noexcept;
314  
};
308  
};
315  

309  

316  
//------------------------------------------------
310  
//------------------------------------------------
317  

311  

318  
/** Format to an output stream
312  
/** Format to an output stream
319  

313  

320  
    Any percent-escapes are emitted as-is;
314  
    Any percent-escapes are emitted as-is;
321  
    no decoding is performed.
315  
    no decoding is performed.
322  

316  

323  
    @par Complexity
317  
    @par Complexity
324  
    Linear in `ps.buffer().size()`.
318  
    Linear in `ps.buffer().size()`.
325  

319  

326  
    @par Effects
320  
    @par Effects
327  
    @code
321  
    @code
328  
    return os << ps.buffer();
322  
    return os << ps.buffer();
329  
    @endcode
323  
    @endcode
330  

324  

331  
    @param os The output stream to write to.
325  
    @param os The output stream to write to.
332  
    @param ps The segments to write.
326  
    @param ps The segments to write.
333  
    @return A reference to the output stream.
327  
    @return A reference to the output stream.
334  
*/
328  
*/
335  
BOOST_URL_DECL
329  
BOOST_URL_DECL
336  
std::ostream&
330  
std::ostream&
337  
operator<<(
331  
operator<<(
338  
    std::ostream& os,
332  
    std::ostream& os,
339  
    segments_base const& ps);
333  
    segments_base const& ps);
340  

334  

341  
} // urls
335  
} // urls
342  
} // boost
336  
} // boost
343  

337  

344  
#include <boost/url/impl/segments_base.hpp>
338  
#include <boost/url/impl/segments_base.hpp>
345  

339  

346  
#endif
340  
#endif