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_URL_VIEW_HPP
11  
#ifndef BOOST_URL_URL_VIEW_HPP
12  
#define BOOST_URL_URL_VIEW_HPP
12  
#define BOOST_URL_URL_VIEW_HPP
13  

13  

14  
#include <boost/url/detail/config.hpp>
14  
#include <boost/url/detail/config.hpp>
15  
#include <boost/url/url_view_base.hpp>
15  
#include <boost/url/url_view_base.hpp>
16  
#include <utility>
16  
#include <utility>
17  

17  

18  
namespace boost {
18  
namespace boost {
19  
namespace urls {
19  
namespace urls {
20  

20  

21  
/** A non-owning reference to a valid URL 
21  
/** A non-owning reference to a valid URL 
22  

22  

23  
    Objects of this type represent valid URL
23  
    Objects of this type represent valid URL
24  
    strings constructed from a parsed, external
24  
    strings constructed from a parsed, external
25  
    character buffer whose storage is managed
25  
    character buffer whose storage is managed
26  
    by the caller. That is, it acts like a
26  
    by the caller. That is, it acts like a
27  
    `core::string_view` in terms of ownership.
27  
    `core::string_view` in terms of ownership.
28  
    The caller is responsible for ensuring
28  
    The caller is responsible for ensuring
29  
    that the lifetime of the underlying
29  
    that the lifetime of the underlying
30  
    character buffer extends until it is no
30  
    character buffer extends until it is no
31  
    longer referenced.
31  
    longer referenced.
32  

32  

33  
    @par Example 1
33  
    @par Example 1
34  
    Construction from a string parses the input
34  
    Construction from a string parses the input
35  
    as a <em>URI-reference</em> and throws an
35  
    as a <em>URI-reference</em> and throws an
36  
    exception on error. Upon success, the
36  
    exception on error. Upon success, the
37  
    constructed object points to the passed
37  
    constructed object points to the passed
38  
    character buffer; ownership is not
38  
    character buffer; ownership is not
39  
    transferred.
39  
    transferred.
40  
    @code
40  
    @code
41  
    url_view u( "https://www.example.com/index.htm?text=none#a1" );
41  
    url_view u( "https://www.example.com/index.htm?text=none#a1" );
42  
    @endcode
42  
    @endcode
43  

43  

44  
    @par Example 2
44  
    @par Example 2
45  
    Parsing functions like @ref parse_uri_reference
45  
    Parsing functions like @ref parse_uri_reference
46  
    return a `boost::system::result` containing either a valid
46  
    return a `boost::system::result` containing either a valid
47  
    @ref url_view upon success, otherwise they
47  
    @ref url_view upon success, otherwise they
48  
    contain an error. The error can be converted to
48  
    contain an error. The error can be converted to
49  
    an exception by the caller if desired:
49  
    an exception by the caller if desired:
50  
    @code
50  
    @code
51  
    system::result< url_view > rv = parse_uri_reference( "https://www.example.com/index.htm?text=none#a1" );
51  
    system::result< url_view > rv = parse_uri_reference( "https://www.example.com/index.htm?text=none#a1" );
52  
    @endcode
52  
    @endcode
53  

53  

54  
    @par BNF
54  
    @par BNF
55  
    @code
55  
    @code
56  
    URI-reference = URI / relative-ref
56  
    URI-reference = URI / relative-ref
57  

57  

58  
    URI           = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
58  
    URI           = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
59  

59  

60  
    relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
60  
    relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
61  
    @endcode
61  
    @endcode
62  

62  

63  
    @par Specification
63  
    @par Specification
64  
    @li <a href="https://tools.ietf.org/html/rfc3986"
64  
    @li <a href="https://tools.ietf.org/html/rfc3986"
65  
        >Uniform Resource Identifier (URI): Generic Syntax (rfc3986)</a>
65  
        >Uniform Resource Identifier (URI): Generic Syntax (rfc3986)</a>
66  

66  

67  
    @see
67  
    @see
68  
        @ref parse_absolute_uri,
68  
        @ref parse_absolute_uri,
69  
        @ref parse_origin_form,
69  
        @ref parse_origin_form,
70  
        @ref parse_relative_ref,
70  
        @ref parse_relative_ref,
71  
        @ref parse_uri,
71  
        @ref parse_uri,
72  
        @ref parse_uri_reference.
72  
        @ref parse_uri_reference.
73  
*/
73  
*/
74  
class BOOST_URL_DECL url_view
74  
class BOOST_URL_DECL url_view
75  
    : public url_view_base
75  
    : public url_view_base
76  
{
76  
{
77  
    friend std::hash<url_view>;
77  
    friend std::hash<url_view>;
78  
    friend class url_view_base;
78  
    friend class url_view_base;
79  
    friend class params_base;
79  
    friend class params_base;
80  
    friend class params_encoded_base;
80  
    friend class params_encoded_base;
81  

81  

82  
#ifndef BOOST_URL_DOCS
82  
#ifndef BOOST_URL_DOCS
83  
    // VFALCO docca emits this erroneously
83  
    // VFALCO docca emits this erroneously
84  
    friend struct detail::url_impl;
84  
    friend struct detail::url_impl;
85  
#endif
85  
#endif
86  

86  

87  
    using url_view_base::digest;
87  
    using url_view_base::digest;
88  

88  

89  
    explicit
89  
    explicit
90  
    url_view(
90  
    url_view(
91  
        detail::url_impl const& impl) noexcept
91  
        detail::url_impl const& impl) noexcept
92  
        : url_view_base(impl)
92  
        : url_view_base(impl)
93  
    {
93  
    {
94  
    }
94  
    }
95  

95  

96  
public:
96  
public:
97  
    //--------------------------------------------
97  
    //--------------------------------------------
98  
    //
98  
    //
99  
    // Special Members
99  
    // Special Members
100  
    //
100  
    //
101  
    //--------------------------------------------
101  
    //--------------------------------------------
102  

102  

103  
    /** Destructor
103  
    /** Destructor
104  

104  

105  
        Any params, segments, iterators, or
105  
        Any params, segments, iterators, or
106  
        other views which reference the same
106  
        other views which reference the same
107  
        underlying character buffer remain
107  
        underlying character buffer remain
108  
        valid.
108  
        valid.
109  
    */
109  
    */
110  
    ~url_view() = default;
110  
    ~url_view() = default;
111  

111  

112  
    /** Constructor
112  
    /** Constructor
113  

113  

114  
        Default constructed views refer to
114  
        Default constructed views refer to
115  
        a string with zero length, which
115  
        a string with zero length, which
116  
        always remains valid. This matches
116  
        always remains valid. This matches
117  
        the grammar for a relative-ref with
117  
        the grammar for a relative-ref with
118  
        an empty path and no query or
118  
        an empty path and no query or
119  
        fragment.
119  
        fragment.
120  

120  

121  
        @par Example
121  
        @par Example
122  
        @code
122  
        @code
123  
        url_view u;
123  
        url_view u;
124  
        @endcode
124  
        @endcode
125  

125  

126  
        @par Postconditions
126  
        @par Postconditions
127  
        @code
127  
        @code
128  
        this->empty() == true
128  
        this->empty() == true
129  
        @endcode
129  
        @endcode
130  

130  

131  
        @par Complexity
131  
        @par Complexity
132  
        Constant.
132  
        Constant.
133  

133  

134  
        @par Exception Safety
134  
        @par Exception Safety
135  
        Throws nothing.
135  
        Throws nothing.
136  

136  

137  
        @par BNF
137  
        @par BNF
138  
        @code
138  
        @code
139  
        relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
139  
        relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
140  
        @endcode
140  
        @endcode
141  

141  

142  
        @par Specification
142  
        @par Specification
143  
        <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.2"
143  
        <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.2"
144  
            >4.2. Relative Reference (rfc3986)</a>
144  
            >4.2. Relative Reference (rfc3986)</a>
145  
    */
145  
    */
146  
    url_view() noexcept;
146  
    url_view() noexcept;
147  

147  

148  
    /** Constructor
148  
    /** Constructor
149  

149  

150  
        This function constructs a URL from
150  
        This function constructs a URL from
151  
        the string `s`, which must contain a
151  
        the string `s`, which must contain a
152  
        valid <em>URI</em> or <em>relative-ref</em>
152  
        valid <em>URI</em> or <em>relative-ref</em>
153  
        or else an exception is thrown. Upon
153  
        or else an exception is thrown. Upon
154  
        successful construction, the view
154  
        successful construction, the view
155  
        refers to the characters in the
155  
        refers to the characters in the
156  
        buffer pointed to by `s`.
156  
        buffer pointed to by `s`.
157  
        Ownership is not transferred; The caller
157  
        Ownership is not transferred; The caller
158  
        is responsible for ensuring that the
158  
        is responsible for ensuring that the
159  
        lifetime of the buffer extends until
159  
        lifetime of the buffer extends until
160  
        it is no longer referenced.
160  
        it is no longer referenced.
161  

161  

162  
        @par Example
162  
        @par Example
163  
        @code
163  
        @code
164  
        url_view u( "http://www.example.com/index.htm" );
164  
        url_view u( "http://www.example.com/index.htm" );
165  
        @endcode
165  
        @endcode
166  

166  

167  
        @par Effects
167  
        @par Effects
168  
        @code
168  
        @code
169  
        return parse_uri_reference( s ).value();
169  
        return parse_uri_reference( s ).value();
170  
        @endcode
170  
        @endcode
171  

171  

172  
        @par Complexity
172  
        @par Complexity
173  
        Linear in `s.size()`.
173  
        Linear in `s.size()`.
174  

174  

175  
        @par Exception Safety
175  
        @par Exception Safety
176  
        Exceptions thrown on invalid input.
176  
        Exceptions thrown on invalid input.
177  

177  

178  
        @throw system_error
178  
        @throw system_error
179  
        The input failed to parse correctly.
179  
        The input failed to parse correctly.
180  

180  

181  
        @param s The string to parse.
181  
        @param s The string to parse.
182  

182  

183  
        @par BNF
183  
        @par BNF
184  
        @code
184  
        @code
185  
        URI           = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
185  
        URI           = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
186  

186  

187  
        relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
187  
        relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
188  
        @endcode
188  
        @endcode
189  

189  

190  
        @par Specification
190  
        @par Specification
191  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.1"
191  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.1"
192  
            >4.1. URI Reference</a>
192  
            >4.1. URI Reference</a>
193  

193  

194  
        @see
194  
        @see
195  
            @ref parse_uri_reference.
195  
            @ref parse_uri_reference.
196  
    */
196  
    */
197  
    url_view(core::string_view s);
197  
    url_view(core::string_view s);
198  

198  

199  
    /// @copydoc url_view(core::string_view)
199  
    /// @copydoc url_view(core::string_view)
200  
    template<
200  
    template<
201  
        class String
201  
        class String
202  
#ifndef BOOST_URL_DOCS
202  
#ifndef BOOST_URL_DOCS
203  
        , class = typename std::enable_if<
203  
        , class = typename std::enable_if<
204  
            std::is_convertible<
204  
            std::is_convertible<
205  
                String,
205  
                String,
206  
                core::string_view
206  
                core::string_view
207  
                    >::value &&
207  
                    >::value &&
208  
            !std::is_convertible<
208  
            !std::is_convertible<
209  
                String*,
209  
                String*,
210  
                url_view_base*
210  
                url_view_base*
211  
                    >::value
211  
                    >::value
212  
            >::type
212  
            >::type
213  
#endif
213  
#endif
214  
    >
214  
    >
215  
    url_view(
215  
    url_view(
216  
        String const& s)
216  
        String const& s)
217  
        : url_view(
217  
        : url_view(
218  
            detail::to_sv(s))
218  
            detail::to_sv(s))
219  
    {
219  
    {
220  
    }
220  
    }
221  

221  

222  
    /** Constructor
222  
    /** Constructor
223  

223  

224  
        After construction, both views
224  
        After construction, both views
225  
        reference the same underlying character
225  
        reference the same underlying character
226  
        buffer. Ownership is not transferred.
226  
        buffer. Ownership is not transferred.
227  

227  

228  
        @par Postconditions
228  
        @par Postconditions
229  
        @code
229  
        @code
230  
        this->buffer().data() == other.buffer().data()
230  
        this->buffer().data() == other.buffer().data()
231  
        @endcode
231  
        @endcode
232  

232  

233  
        @par Complexity
233  
        @par Complexity
234  
        Constant.
234  
        Constant.
235  

235  

236  
        @par Exception Safety
236  
        @par Exception Safety
237  
        Throws nothing.
237  
        Throws nothing.
238  

238  

239  
        @param other The other view.
239  
        @param other The other view.
240  
    */
240  
    */
241  
    url_view(
241  
    url_view(
242  
        url_view const& other) noexcept
242  
        url_view const& other) noexcept
243  
        : url_view(static_cast<
243  
        : url_view(static_cast<
244  
            url_view_base const&>(other))
244  
            url_view_base const&>(other))
245  
    {
245  
    {
246  
    }
246  
    }
247  

247  

248  
    /** Constructor
248  
    /** Constructor
249  

249  

250  
        After construction, both views
250  
        After construction, both views
251  
        reference the same underlying character
251  
        reference the same underlying character
252  
        buffer. Ownership is not transferred.
252  
        buffer. Ownership is not transferred.
253  

253  

254  
        @par Postconditions
254  
        @par Postconditions
255  
        @code
255  
        @code
256  
        this->buffer().data() == other.buffer().data()
256  
        this->buffer().data() == other.buffer().data()
257  
        @endcode
257  
        @endcode
258  

258  

259  
        @par Complexity
259  
        @par Complexity
260  
        Constant.
260  
        Constant.
261  

261  

262  
        @par Exception Safety
262  
        @par Exception Safety
263  
        Throws nothing.
263  
        Throws nothing.
264  

264  

265  
        @param other The other view.
265  
        @param other The other view.
266  
    */
266  
    */
267  
    url_view(
267  
    url_view(
268  
        url_view_base const& other) noexcept;
268  
        url_view_base const& other) noexcept;
269  

269  

270  
    /** Assignment
270  
    /** Assignment
271  

271  

272  
        After assignment, both views
272  
        After assignment, both views
273  
        reference the same underlying character
273  
        reference the same underlying character
274  
        buffer. Ownership is not transferred.
274  
        buffer. Ownership is not transferred.
275  

275  

276  
        @par Postconditions
276  
        @par Postconditions
277  
        @code
277  
        @code
278  
        this->buffer().data() == other.buffer().data()
278  
        this->buffer().data() == other.buffer().data()
279  
        @endcode
279  
        @endcode
280  

280  

281  
        @par Complexity
281  
        @par Complexity
282  
        Constant.
282  
        Constant.
283  

283  

284  
        @par Exception Safety
284  
        @par Exception Safety
285  
        Throws nothing.
285  
        Throws nothing.
286  

286  

287  
        @param other The other view.
287  
        @param other The other view.
288  
        @return A reference to this object.
288  
        @return A reference to this object.
289  
    */
289  
    */
290  
    url_view&
290  
    url_view&
291  
    operator=(
291  
    operator=(
292  
        url_view const& other) noexcept
292  
        url_view const& other) noexcept
293  
    {
293  
    {
294  
        if (this != &other)
294  
        if (this != &other)
295  
            *this = static_cast<
295  
            *this = static_cast<
296  
                url_view_base const&>(other);
296  
                url_view_base const&>(other);
297  
        return *this;
297  
        return *this;
298  
    }
298  
    }
299  

299  

300  
    /** Assignment
300  
    /** Assignment
301  

301  

302  
        After assignment, both views
302  
        After assignment, both views
303  
        reference the same underlying character
303  
        reference the same underlying character
304  
        buffer. Ownership is not transferred.
304  
        buffer. Ownership is not transferred.
305  

305  

306  
        @par Postconditions
306  
        @par Postconditions
307  
        @code
307  
        @code
308  
        this->buffer().data() == other.buffer().data()
308  
        this->buffer().data() == other.buffer().data()
309  
        @endcode
309  
        @endcode
310  

310  

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

313  

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

316  

317  
        @param other The other view.
317  
        @param other The other view.
318  
        @return A reference to this object.
318  
        @return A reference to this object.
319  
    */
319  
    */
320  
    url_view& operator=(
320  
    url_view& operator=(
321  
        url_view_base const& other) noexcept;
321  
        url_view_base const& other) noexcept;
322  

322  

323  
    //--------------------------------------------
323  
    //--------------------------------------------
324  
    //
324  
    //
325  
    // Observers
325  
    // Observers
326  
    //
326  
    //
327  
    //--------------------------------------------
327  
    //--------------------------------------------
328  

328  

329  
    /** Return the maximum number of characters possible
329  
    /** Return the maximum number of characters possible
330  

330  

331  
        This represents the largest number of
331  
        This represents the largest number of
332  
        characters that are possible in a url,
332  
        characters that are possible in a url,
333  
        not including any null terminator.
333  
        not including any null terminator.
334  

334  

335  
        @par Complexity
335  
        @par Complexity
336  
        Constant.
336  
        Constant.
337  

337  

338  
        @par Exception Safety
338  
        @par Exception Safety
339  
        Throws nothing.
339  
        Throws nothing.
340  

340  

341  
        @return The maximum number of characters possible.
341  
        @return The maximum number of characters possible.
342  
    */
342  
    */
343  
    static
343  
    static
344  
    constexpr
344  
    constexpr
345  
    std::size_t
345  
    std::size_t
346  
    max_size() noexcept
346  
    max_size() noexcept
347  
    {
347  
    {
348  
        return BOOST_URL_MAX_SIZE;
348  
        return BOOST_URL_MAX_SIZE;
349  
    }
349  
    }
350  
};
350  
};
351  

351  

352  
} // urls
352  
} // urls
353  
} // boost
353  
} // boost
354  

354  

355  
//------------------------------------------------
355  
//------------------------------------------------
356  

356  

357  
// std::hash specialization
357  
// std::hash specialization
358  
#ifndef BOOST_URL_DOCS
358  
#ifndef BOOST_URL_DOCS
359  
namespace std {
359  
namespace std {
360  
template<>
360  
template<>
361  
struct hash< ::boost::urls::url_view >
361  
struct hash< ::boost::urls::url_view >
362  
{
362  
{
363  
    hash() = default;
363  
    hash() = default;
364  
    hash(hash const&) = default;
364  
    hash(hash const&) = default;
365  
    hash& operator=(hash const&) = default;
365  
    hash& operator=(hash const&) = default;
366  

366  

367  
    explicit
367  
    explicit
368  
    hash(std::size_t salt) noexcept
368  
    hash(std::size_t salt) noexcept
369  
        : salt_(salt)
369  
        : salt_(salt)
370  
    {
370  
    {
371  
    }
371  
    }
372  

372  

373  
    std::size_t
373  
    std::size_t
374  
    operator()(::boost::urls::url_view const& u) const noexcept
374  
    operator()(::boost::urls::url_view const& u) const noexcept
375  
    {
375  
    {
376  
        return u.digest(salt_);
376  
        return u.digest(salt_);
377  
    }
377  
    }
378  

378  

379  
private:
379  
private:
380  
    std::size_t salt_ = 0;
380  
    std::size_t salt_ = 0;
381  
};
381  
};
382  
} // std
382  
} // std
383  
#endif
383  
#endif
384  

384  

385  
#endif
385  
#endif