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 BOOST_SYMBOL_VISIBLE segments_base
38  
class BOOST_SYMBOL_VISIBLE 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  
    */
154  
    */
155  
    pct_string_view
155  
    pct_string_view
156  
    buffer() const noexcept;
156  
    buffer() const noexcept;
157  

157  

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

159  

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

162  

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

167  

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

170  

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

173  

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

178  

179  
    /** Return true if there are no segments
179  
    /** Return true if there are no segments
180  

180  

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

185  

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

188  

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

191  

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

196  

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

203  

204  
        @par Complexity
204  
        @par Complexity
205  
        Constant.
205  
        Constant.
206  

206  

207  
        @par Exception Safety
207  
        @par Exception Safety
208  
        Throws nothing.
208  
        Throws nothing.
209  

209  

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

214  

215  
    /** Return the first segment
215  
    /** Return the first segment
216  

216  

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

222  

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

227  

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

232  

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

237  

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

240  

241  
        @par Exception Safety
241  
        @par Exception Safety
242  
        Calls to allocate may throw.
242  
        Calls to allocate may throw.
243  

243  

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

248  

249  
    /** Return the last segment
249  
    /** Return the last segment
250  

250  

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

255  

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

260  

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

265  

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

270  

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

273  

274  
        @par Exception Safety
274  
        @par Exception Safety
275  
        Calls to allocate may throw.
275  
        Calls to allocate may throw.
276  

276  

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

281  

282  
    /** Return an iterator to the beginning
282  
    /** Return an iterator to the beginning
283  

283  

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

287  

288  
        @par Exception Safety
288  
        @par Exception Safety
289  
        Throws nothing.
289  
        Throws nothing.
290  

290  

291  
        @return An iterator to the first segment.
291  
        @return An iterator to the first segment.
292  
    */
292  
    */
293  
    iterator
293  
    iterator
294  
    begin() const noexcept;
294  
    begin() const noexcept;
295  

295  

296  
    /** Return an iterator to the end
296  
    /** Return an iterator to the end
297  

297  

298  
        @par Complexity
298  
        @par Complexity
299  
        Constant.
299  
        Constant.
300  

300  

301  
        @par Exception Safety
301  
        @par Exception Safety
302  
        Throws nothing.
302  
        Throws nothing.
303  

303  

304  
        @return An iterator to one past the last segment.
304  
        @return An iterator to one past the last segment.
305  
    */
305  
    */
306  
    iterator
306  
    iterator
307  
    end() const noexcept;
307  
    end() const noexcept;
308  
};
308  
};
309  

309  

310  
//------------------------------------------------
310  
//------------------------------------------------
311  

311  

312  
/** Format to an output stream
312  
/** Format to an output stream
313  

313  

314  
    Any percent-escapes are emitted as-is;
314  
    Any percent-escapes are emitted as-is;
315  
    no decoding is performed.
315  
    no decoding is performed.
316  

316  

317  
    @par Complexity
317  
    @par Complexity
318  
    Linear in `ps.buffer().size()`.
318  
    Linear in `ps.buffer().size()`.
319  

319  

320  
    @par Effects
320  
    @par Effects
321  
    @code
321  
    @code
322  
    return os << ps.buffer();
322  
    return os << ps.buffer();
323  
    @endcode
323  
    @endcode
324  

324  

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

333  

334  
} // urls
334  
} // urls
335  
} // boost
335  
} // boost
336  

336  

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

338  

339  
#endif
339  
#endif