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 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 +
    BOOST_URL_CXX14_CONSTEXPR
89  
    explicit
90  
    explicit
90  
    url_view(
91  
    url_view(
91  
        detail::url_impl const& impl) noexcept
92  
        detail::url_impl const& impl) noexcept
92  
        : url_view_base(impl)
93  
        : url_view_base(impl)
93  
    {
94  
    {
94  
    }
95  
    }
95  

96  

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

103  

103  
    /** Destructor
104  
    /** Destructor
104  

105  

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

112  

112  
    /** Constructor
113  
    /** Constructor
113  

114  

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

121  

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

126  

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

131  

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

134  

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

137  

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

142  

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

149  

148  
    /** Constructor
150  
    /** Constructor
149  

151  

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

163  

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

168  

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

173  

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

176  

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

179  

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

182  

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

184  

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

188  

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

191  

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

195  

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

200  

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

223  

222  
    /** Constructor
224  
    /** Constructor
223  

225  

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

229  

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

234  

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

237  

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

240  

239  
        @param other The other view.
241  
        @param other The other view.
240  
    */
242  
    */
 
243 +
    BOOST_URL_CXX14_CONSTEXPR
241  
    url_view(
244  
    url_view(
242 -
        url_view const& other) noexcept
245 +
        url_view const& other) noexcept = default;
243 -
        : url_view(static_cast<
246 +

244 -
            url_view_base const&>(other))
247 +
    /** Move constructor
245 -
    {
248 +
    */
246 -
    }
249 +
    BOOST_URL_CXX14_CONSTEXPR
 
250 +
    url_view(
 
251 +
        url_view&& other) noexcept = default;
247  

252  

248  
    /** Constructor
253  
    /** Constructor
249  

254  

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

258  

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

263  

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

266  

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

269  

265  
        @param other The other view.
270  
        @param other The other view.
266  
    */
271  
    */
 
272 +
    BOOST_URL_CXX14_CONSTEXPR
267  
    url_view(
273  
    url_view(
268 -
        url_view_base const& other) noexcept;
274 +
        url_view_base const& other) noexcept
 
275 +
        : url_view_base(other.impl_)
 
276 +
    {
 
277 +
        external_impl_ = other.external_impl_;
 
278 +
    }
269  

279  

270  
    /** Assignment
280  
    /** Assignment
271  

281  

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

285  

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

290  

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

293  

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

296  

287  
        @param other The other view.
297  
        @param other The other view.
288  
        @return A reference to this object.
298  
        @return A reference to this object.
289  
    */
299  
    */
 
300 +
    BOOST_URL_CXX14_CONSTEXPR
290  
    url_view&
301  
    url_view&
291  
    operator=(
302  
    operator=(
292  
        url_view const& other) noexcept
303  
        url_view const& other) noexcept
293  
    {
304  
    {
294 -
        if (this != &other)
305 +
        impl_ = other.impl_;
295 -
            *this = static_cast<
306 +
        external_impl_ = other.external_impl_;
296 -
                url_view_base const&>(other);
 
297  
        return *this;
307  
        return *this;
298  
    }
308  
    }
299  

309  

300  
    /** Assignment
310  
    /** Assignment
301  

311  

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

315  

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

320  

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

323  

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

326  

317  
        @param other The other view.
327  
        @param other The other view.
318  
        @return A reference to this object.
328  
        @return A reference to this object.
319  
    */
329  
    */
 
330 +
    BOOST_URL_CXX14_CONSTEXPR
320  
    url_view& operator=(
331  
    url_view& operator=(
321 -
        url_view_base const& other) noexcept;
332 +
        url_view_base const& other) noexcept
 
333 +
    {
 
334 +
        impl_ = other.impl_;
 
335 +
        external_impl_ = other.external_impl_;
 
336 +
        return *this;
 
337 +
    }
322  

338  

323  
    //--------------------------------------------
339  
    //--------------------------------------------
324  
    //
340  
    //
325  
    // Observers
341  
    // Observers
326  
    //
342  
    //
327  
    //--------------------------------------------
343  
    //--------------------------------------------
328  

344  

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

346  

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

350  

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

353  

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

356  

341  
        @return The maximum number of characters possible.
357  
        @return The maximum number of characters possible.
342  
    */
358  
    */
343  
    static
359  
    static
344  
    constexpr
360  
    constexpr
345  
    std::size_t
361  
    std::size_t
346  
    max_size() noexcept
362  
    max_size() noexcept
347  
    {
363  
    {
348  
        return BOOST_URL_MAX_SIZE;
364  
        return BOOST_URL_MAX_SIZE;
349  
    }
365  
    }
350  
};
366  
};
351  

367  

 
368 +
namespace detail {
 
369 +

 
370 +
inline BOOST_URL_CXX14_CONSTEXPR
 
371 +
url_view
 
372 +
url_impl::
 
373 +
construct() const noexcept
 
374 +
{
 
375 +
    return url_view(*this);
 
376 +
}
 
377 +

 
378 +
} // detail
 
379 +

352  
} // urls
380  
} // urls
353  
} // boost
381  
} // boost
354  

382  

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

384  

357  
// std::hash specialization
385  
// std::hash specialization
358  
#ifndef BOOST_URL_DOCS
386  
#ifndef BOOST_URL_DOCS
359  
namespace std {
387  
namespace std {
360  
template<>
388  
template<>
361  
struct hash< ::boost::urls::url_view >
389  
struct hash< ::boost::urls::url_view >
362  
{
390  
{
363  
    hash() = default;
391  
    hash() = default;
364  
    hash(hash const&) = default;
392  
    hash(hash const&) = default;
365  
    hash& operator=(hash const&) = default;
393  
    hash& operator=(hash const&) = default;
366  

394  

367  
    explicit
395  
    explicit
368  
    hash(std::size_t salt) noexcept
396  
    hash(std::size_t salt) noexcept
369  
        : salt_(salt)
397  
        : salt_(salt)
370  
    {
398  
    {
371  
    }
399  
    }
372  

400  

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

406  

379  
private:
407  
private:
380  
    std::size_t salt_ = 0;
408  
    std::size_t salt_ = 0;
381  
};
409  
};
382  
} // std
410  
} // std
383  
#endif
411  
#endif
 
412 +

 
413 +
#include <boost/url/impl/url_view.hpp>
 
414 +
#include <boost/url/parse.hpp>
384  

415  

385  
#endif
416  
#endif