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  
namespace implementation_defined {
21  
namespace implementation_defined {
22  
struct origin_form_rule_t;
22  
struct origin_form_rule_t;
23  
struct uri_rule_t;
23  
struct uri_rule_t;
24  
struct relative_ref_rule_t;
24  
struct relative_ref_rule_t;
25  
struct absolute_uri_rule_t;
25  
struct absolute_uri_rule_t;
26  
} // implementation_defined
26  
} // implementation_defined
27  

27  

28  
/** A non-owning reference to a valid URL 
28  
/** A non-owning reference to a valid URL 
29  

29  

30  
    Objects of this type represent valid URL
30  
    Objects of this type represent valid URL
31  
    strings constructed from a parsed, external
31  
    strings constructed from a parsed, external
32  
    character buffer whose storage is managed
32  
    character buffer whose storage is managed
33  
    by the caller. That is, it acts like a
33  
    by the caller. That is, it acts like a
34  
    `core::string_view` in terms of ownership.
34  
    `core::string_view` in terms of ownership.
35  
    The caller is responsible for ensuring
35  
    The caller is responsible for ensuring
36  
    that the lifetime of the underlying
36  
    that the lifetime of the underlying
37  
    character buffer extends until it is no
37  
    character buffer extends until it is no
38  
    longer referenced.
38  
    longer referenced.
39  

39  

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

50  

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

60  

61  
    @par BNF
61  
    @par BNF
62  
    @code
62  
    @code
63  
    URI-reference = URI / relative-ref
63  
    URI-reference = URI / relative-ref
64  

64  

65  
    URI           = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
65  
    URI           = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
66  

66  

67  
    relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
67  
    relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
68  
    @endcode
68  
    @endcode
69  

69  

70  
    @par Specification
70  
    @par Specification
71  
    @li <a href="https://tools.ietf.org/html/rfc3986"
71  
    @li <a href="https://tools.ietf.org/html/rfc3986"
72  
        >Uniform Resource Identifier (URI): Generic Syntax (rfc3986)</a>
72  
        >Uniform Resource Identifier (URI): Generic Syntax (rfc3986)</a>
73  

73  

74  
    @see
74  
    @see
75  
        @ref parse_absolute_uri,
75  
        @ref parse_absolute_uri,
76  
        @ref parse_origin_form,
76  
        @ref parse_origin_form,
77  
        @ref parse_relative_ref,
77  
        @ref parse_relative_ref,
78  
        @ref parse_uri,
78  
        @ref parse_uri,
79  
        @ref parse_uri_reference.
79  
        @ref parse_uri_reference.
80  
*/
80  
*/
81  
class BOOST_SYMBOL_VISIBLE url_view
81  
class BOOST_SYMBOL_VISIBLE url_view
82  
    : public url_view_base
82  
    : public url_view_base
83  
{
83  
{
84  
    friend std::hash<url_view>;
84  
    friend std::hash<url_view>;
85  
    friend class url_view_base;
85  
    friend class url_view_base;
86  
    friend class params_base;
86  
    friend class params_base;
87  
    friend class params_encoded_base;
87  
    friend class params_encoded_base;
88  
    friend struct implementation_defined::origin_form_rule_t;
88  
    friend struct implementation_defined::origin_form_rule_t;
89  
    friend struct implementation_defined::uri_rule_t;
89  
    friend struct implementation_defined::uri_rule_t;
90  
    friend struct implementation_defined::relative_ref_rule_t;
90  
    friend struct implementation_defined::relative_ref_rule_t;
91  
    friend struct implementation_defined::absolute_uri_rule_t;
91  
    friend struct implementation_defined::absolute_uri_rule_t;
92  

92  

93  
    using url_view_base::digest;
93  
    using url_view_base::digest;
94  

94  

95  
    BOOST_URL_CXX14_CONSTEXPR
95  
    BOOST_URL_CXX14_CONSTEXPR
96  
    explicit
96  
    explicit
97  
    url_view(
97  
    url_view(
98  
        detail::url_impl const& impl) noexcept
98  
        detail::url_impl const& impl) noexcept
99  
        : url_view_base(impl)
99  
        : url_view_base(impl)
100  
    {
100  
    {
101  
    }
101  
    }
102  

102  

103  
public:
103  
public:
104  
    //--------------------------------------------
104  
    //--------------------------------------------
105  
    //
105  
    //
106  
    // Special Members
106  
    // Special Members
107  
    //
107  
    //
108  
    //--------------------------------------------
108  
    //--------------------------------------------
109  

109  

110  
    /** Destructor
110  
    /** Destructor
111  

111  

112  
        Any params, segments, iterators, or
112  
        Any params, segments, iterators, or
113  
        other views which reference the same
113  
        other views which reference the same
114  
        underlying character buffer remain
114  
        underlying character buffer remain
115  
        valid.
115  
        valid.
116  
    */
116  
    */
117  
    ~url_view() = default;
117  
    ~url_view() = default;
118  

118  

119  
    /** Constructor
119  
    /** Constructor
120  

120  

121  
        Default constructed views refer to
121  
        Default constructed views refer to
122  
        a string with zero length, which
122  
        a string with zero length, which
123  
        always remains valid. This matches
123  
        always remains valid. This matches
124  
        the grammar for a relative-ref with
124  
        the grammar for a relative-ref with
125  
        an empty path and no query or
125  
        an empty path and no query or
126  
        fragment.
126  
        fragment.
127  

127  

128  
        @par Example
128  
        @par Example
129  
        @code
129  
        @code
130  
        url_view u;
130  
        url_view u;
131  
        @endcode
131  
        @endcode
132  

132  

133  
        @par Postconditions
133  
        @par Postconditions
134  
        @code
134  
        @code
135  
        this->empty() == true
135  
        this->empty() == true
136  
        @endcode
136  
        @endcode
137  

137  

138  
        @par Complexity
138  
        @par Complexity
139  
        Constant.
139  
        Constant.
140  

140  

141  
        @par Exception Safety
141  
        @par Exception Safety
142  
        Throws nothing.
142  
        Throws nothing.
143  

143  

144  
        @par BNF
144  
        @par BNF
145  
        @code
145  
        @code
146  
        relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
146  
        relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
147  
        @endcode
147  
        @endcode
148  

148  

149  
        @par Specification
149  
        @par Specification
150  
        <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.2"
150  
        <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.2"
151  
            >4.2. Relative Reference (rfc3986)</a>
151  
            >4.2. Relative Reference (rfc3986)</a>
152  
    */
152  
    */
153  
    BOOST_URL_CXX14_CONSTEXPR
153  
    BOOST_URL_CXX14_CONSTEXPR
154  
    url_view() noexcept = default;
154  
    url_view() noexcept = default;
155  

155  

156  
    /** Constructor
156  
    /** Constructor
157  

157  

158  
        This function constructs a URL from
158  
        This function constructs a URL from
159  
        the string `s`, which must contain a
159  
        the string `s`, which must contain a
160  
        valid <em>URI</em> or <em>relative-ref</em>
160  
        valid <em>URI</em> or <em>relative-ref</em>
161  
        or else an exception is thrown. Upon
161  
        or else an exception is thrown. Upon
162  
        successful construction, the view
162  
        successful construction, the view
163  
        refers to the characters in the
163  
        refers to the characters in the
164  
        buffer pointed to by `s`.
164  
        buffer pointed to by `s`.
165  
        Ownership is not transferred; The caller
165  
        Ownership is not transferred; The caller
166  
        is responsible for ensuring that the
166  
        is responsible for ensuring that the
167  
        lifetime of the buffer extends until
167  
        lifetime of the buffer extends until
168  
        it is no longer referenced.
168  
        it is no longer referenced.
169  

169  

170  
        @par Example
170  
        @par Example
171  
        @code
171  
        @code
172  
        url_view u( "http://www.example.com/index.htm" );
172  
        url_view u( "http://www.example.com/index.htm" );
173  
        @endcode
173  
        @endcode
174  

174  

175  
        @par Effects
175  
        @par Effects
176  
        @code
176  
        @code
177  
        return parse_uri_reference( s ).value();
177  
        return parse_uri_reference( s ).value();
178  
        @endcode
178  
        @endcode
179  

179  

180  
        @par Complexity
180  
        @par Complexity
181  
        Linear in `s.size()`.
181  
        Linear in `s.size()`.
182  

182  

183  
        @par Exception Safety
183  
        @par Exception Safety
184  
        Exceptions thrown on invalid input.
184  
        Exceptions thrown on invalid input.
185  

185  

186  
        @throw system_error
186  
        @throw system_error
187  
        The input failed to parse correctly.
187  
        The input failed to parse correctly.
188  

188  

189  
        @param s The string to parse.
189  
        @param s The string to parse.
190  

190  

191  
        @par BNF
191  
        @par BNF
192  
        @code
192  
        @code
193  
        URI           = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
193  
        URI           = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
194  

194  

195  
        relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
195  
        relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
196  
        @endcode
196  
        @endcode
197  

197  

198  
        @par Specification
198  
        @par Specification
199  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.1"
199  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.1"
200  
            >4.1. URI Reference</a>
200  
            >4.1. URI Reference</a>
201  

201  

202  
        @see
202  
        @see
203  
            @ref parse_uri_reference.
203  
            @ref parse_uri_reference.
204  
    */
204  
    */
205  
    url_view(core::string_view s);
205  
    url_view(core::string_view s);
206  

206  

207  
    /// @copydoc url_view(core::string_view)
207  
    /// @copydoc url_view(core::string_view)
208  
    template<
208  
    template<
209  
        class String
209  
        class String
210  
#ifndef BOOST_URL_DOCS
210  
#ifndef BOOST_URL_DOCS
211  
        , class = typename std::enable_if<
211  
        , class = typename std::enable_if<
212  
            std::is_convertible<
212  
            std::is_convertible<
213  
                String,
213  
                String,
214  
                core::string_view
214  
                core::string_view
215  
                    >::value &&
215  
                    >::value &&
216  
            !std::is_convertible<
216  
            !std::is_convertible<
217  
                String*,
217  
                String*,
218  
                url_view_base*
218  
                url_view_base*
219  
                    >::value
219  
                    >::value
220  
            >::type
220  
            >::type
221  
#endif
221  
#endif
222  
    >
222  
    >
223  
    url_view(
223  
    url_view(
224  
        String const& s)
224  
        String const& s)
225  
        : url_view(
225  
        : url_view(
226  
            detail::to_sv(s))
226  
            detail::to_sv(s))
227  
    {
227  
    {
228  
    }
228  
    }
229  

229  

230  
    /** Constructor
230  
    /** Constructor
231  

231  

232  
        After construction, both views
232  
        After construction, both views
233  
        reference the same underlying character
233  
        reference the same underlying character
234  
        buffer. Ownership is not transferred.
234  
        buffer. Ownership is not transferred.
235  

235  

236  
        @par Postconditions
236  
        @par Postconditions
237  
        @code
237  
        @code
238  
        this->buffer().data() == other.buffer().data()
238  
        this->buffer().data() == other.buffer().data()
239  
        @endcode
239  
        @endcode
240  

240  

241  
        @par Complexity
241  
        @par Complexity
242  
        Constant.
242  
        Constant.
243  

243  

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

246  

247  
        @param other The other view.
247  
        @param other The other view.
248  
    */
248  
    */
249  
    BOOST_URL_CXX14_CONSTEXPR
249  
    BOOST_URL_CXX14_CONSTEXPR
250  
    url_view(
250  
    url_view(
251  
        url_view const& other) noexcept = default;
251  
        url_view const& other) noexcept = default;
252  

252  

253  
    /** Move constructor
253  
    /** Move constructor
254  
    */
254  
    */
255  
    BOOST_URL_CXX14_CONSTEXPR
255  
    BOOST_URL_CXX14_CONSTEXPR
256  
    url_view(
256  
    url_view(
257  
        url_view&& other) noexcept = default;
257  
        url_view&& other) noexcept = default;
258  

258  

259  
    /** Constructor
259  
    /** Constructor
260  

260  

261  
        After construction, both views
261  
        After construction, both views
262  
        reference the same underlying character
262  
        reference the same underlying character
263  
        buffer. Ownership is not transferred.
263  
        buffer. Ownership is not transferred.
264  

264  

265  
        @par Postconditions
265  
        @par Postconditions
266  
        @code
266  
        @code
267  
        this->buffer().data() == other.buffer().data()
267  
        this->buffer().data() == other.buffer().data()
268  
        @endcode
268  
        @endcode
269  

269  

270  
        @par Complexity
270  
        @par Complexity
271  
        Constant.
271  
        Constant.
272  

272  

273  
        @par Exception Safety
273  
        @par Exception Safety
274  
        Throws nothing.
274  
        Throws nothing.
275  

275  

276  
        @param other The other view.
276  
        @param other The other view.
277  
    */
277  
    */
278  
    BOOST_URL_CXX14_CONSTEXPR
278  
    BOOST_URL_CXX14_CONSTEXPR
279  
    url_view(
279  
    url_view(
280  
        url_view_base const& other) noexcept
280  
        url_view_base const& other) noexcept
281  
        : url_view_base(other.impl_)
281  
        : url_view_base(other.impl_)
282  
    {
282  
    {
283  
        external_impl_ = other.external_impl_;
283  
        external_impl_ = other.external_impl_;
284  
    }
284  
    }
285  

285  

286  
    /** Assignment
286  
    /** Assignment
287  

287  

288  
        After assignment, both views
288  
        After assignment, both views
289  
        reference the same underlying character
289  
        reference the same underlying character
290  
        buffer. Ownership is not transferred.
290  
        buffer. Ownership is not transferred.
291  

291  

292  
        @par Postconditions
292  
        @par Postconditions
293  
        @code
293  
        @code
294  
        this->buffer().data() == other.buffer().data()
294  
        this->buffer().data() == other.buffer().data()
295  
        @endcode
295  
        @endcode
296  

296  

297  
        @par Complexity
297  
        @par Complexity
298  
        Constant.
298  
        Constant.
299  

299  

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

302  

303  
        @param other The other view.
303  
        @param other The other view.
304  
        @return A reference to this object.
304  
        @return A reference to this object.
305  
    */
305  
    */
306  
    BOOST_URL_CXX14_CONSTEXPR
306  
    BOOST_URL_CXX14_CONSTEXPR
307  
    url_view&
307  
    url_view&
308  
    operator=(
308  
    operator=(
309  
        url_view const& other) noexcept
309  
        url_view const& other) noexcept
310  
    {
310  
    {
311  
        impl_ = other.impl_;
311  
        impl_ = other.impl_;
312  
        external_impl_ = other.external_impl_;
312  
        external_impl_ = other.external_impl_;
313  
        return *this;
313  
        return *this;
314  
    }
314  
    }
315  

315  

316  
    /** Assignment
316  
    /** Assignment
317  

317  

318  
        After assignment, both views
318  
        After assignment, both views
319  
        reference the same underlying character
319  
        reference the same underlying character
320  
        buffer. Ownership is not transferred.
320  
        buffer. Ownership is not transferred.
321  

321  

322  
        @par Postconditions
322  
        @par Postconditions
323  
        @code
323  
        @code
324  
        this->buffer().data() == other.buffer().data()
324  
        this->buffer().data() == other.buffer().data()
325  
        @endcode
325  
        @endcode
326  

326  

327  
        @par Complexity
327  
        @par Complexity
328  
        Constant.
328  
        Constant.
329  

329  

330  
        @par Exception Safety
330  
        @par Exception Safety
331  
        Throws nothing.
331  
        Throws nothing.
332  

332  

333  
        @param other The other view.
333  
        @param other The other view.
334  
        @return A reference to this object.
334  
        @return A reference to this object.
335  
    */
335  
    */
336  
    BOOST_URL_CXX14_CONSTEXPR
336  
    BOOST_URL_CXX14_CONSTEXPR
337  
    url_view& operator=(
337  
    url_view& operator=(
338  
        url_view_base const& other) noexcept
338  
        url_view_base const& other) noexcept
339  
    {
339  
    {
340  
        impl_ = other.impl_;
340  
        impl_ = other.impl_;
341  
        external_impl_ = other.external_impl_;
341  
        external_impl_ = other.external_impl_;
342  
        return *this;
342  
        return *this;
343  
    }
343  
    }
344  

344  

345  
    //--------------------------------------------
345  
    //--------------------------------------------
346  
    //
346  
    //
347  
    // Observers
347  
    // Observers
348  
    //
348  
    //
349  
    //--------------------------------------------
349  
    //--------------------------------------------
350  

350  

351  
    /** Return the maximum number of characters possible
351  
    /** Return the maximum number of characters possible
352  

352  

353  
        This represents the largest number of
353  
        This represents the largest number of
354  
        characters that are possible in a url,
354  
        characters that are possible in a url,
355  
        not including any null terminator.
355  
        not including any null terminator.
356  

356  

357  
        @par Complexity
357  
        @par Complexity
358  
        Constant.
358  
        Constant.
359  

359  

360  
        @par Exception Safety
360  
        @par Exception Safety
361  
        Throws nothing.
361  
        Throws nothing.
362  

362  

363  
        @return The maximum number of characters possible.
363  
        @return The maximum number of characters possible.
364  
    */
364  
    */
365  
    static
365  
    static
366  
    constexpr
366  
    constexpr
367  
    std::size_t
367  
    std::size_t
368  
    max_size() noexcept
368  
    max_size() noexcept
369  
    {
369  
    {
370  
        return BOOST_URL_MAX_SIZE;
370  
        return BOOST_URL_MAX_SIZE;
371  
    }
371  
    }
372  
};
372  
};
373  

373  

374  
} // urls
374  
} // urls
375  
} // boost
375  
} // boost
376  

376  

377  
//------------------------------------------------
377  
//------------------------------------------------
378  

378  

379  
// std::hash specialization
379  
// std::hash specialization
380  
#ifndef BOOST_URL_DOCS
380  
#ifndef BOOST_URL_DOCS
381  
namespace std {
381  
namespace std {
382  
template<>
382  
template<>
383  
struct hash< ::boost::urls::url_view >
383  
struct hash< ::boost::urls::url_view >
384  
{
384  
{
385  
    hash() = default;
385  
    hash() = default;
386  
    hash(hash const&) = default;
386  
    hash(hash const&) = default;
387  
    hash& operator=(hash const&) = default;
387  
    hash& operator=(hash const&) = default;
388  

388  

389  
    explicit
389  
    explicit
390  
    hash(std::size_t salt) noexcept
390  
    hash(std::size_t salt) noexcept
391  
        : salt_(salt)
391  
        : salt_(salt)
392  
    {
392  
    {
393  
    }
393  
    }
394  

394  

395  
    std::size_t
395  
    std::size_t
396  
    operator()(::boost::urls::url_view const& u) const noexcept
396  
    operator()(::boost::urls::url_view const& u) const noexcept
397  
    {
397  
    {
398  
        return u.digest(salt_);
398  
        return u.digest(salt_);
399  
    }
399  
    }
400  

400  

401  
private:
401  
private:
402  
    std::size_t salt_ = 0;
402  
    std::size_t salt_ = 0;
403  
};
403  
};
404  
} // std
404  
} // std
405  
#endif
405  
#endif
406  

406  

407  
// When parse.hpp is being processed,
407  
// When parse.hpp is being processed,
408  
// it will include impl/url_view.hpp itself
408  
// it will include impl/url_view.hpp itself
409  
// after declaring parse_uri_reference.
409  
// after declaring parse_uri_reference.
410  
#if !defined(BOOST_URL_PARSE_HPP)
410  
#if !defined(BOOST_URL_PARSE_HPP)
411  
#include <boost/url/impl/url_view.hpp>
411  
#include <boost/url/impl/url_view.hpp>
412  
#endif
412  
#endif
413  

413  

414  
#endif
414  
#endif