Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
4 : //
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)
7 : //
8 : // Official repository: https://github.com/boostorg/url
9 : //
10 :
11 : #ifndef BOOST_URL_URL_VIEW_HPP
12 : #define BOOST_URL_URL_VIEW_HPP
13 :
14 : #include <boost/url/detail/config.hpp>
15 : #include <boost/url/url_view_base.hpp>
16 : #include <utility>
17 :
18 : namespace boost {
19 : namespace urls {
20 :
21 : /** A non-owning reference to a valid URL
22 :
23 : Objects of this type represent valid URL
24 : strings constructed from a parsed, external
25 : character buffer whose storage is managed
26 : by the caller. That is, it acts like a
27 : `core::string_view` in terms of ownership.
28 : The caller is responsible for ensuring
29 : that the lifetime of the underlying
30 : character buffer extends until it is no
31 : longer referenced.
32 :
33 : @par Example 1
34 : Construction from a string parses the input
35 : as a <em>URI-reference</em> and throws an
36 : exception on error. Upon success, the
37 : constructed object points to the passed
38 : character buffer; ownership is not
39 : transferred.
40 : @code
41 : url_view u( "https://www.example.com/index.htm?text=none#a1" );
42 : @endcode
43 :
44 : @par Example 2
45 : Parsing functions like @ref parse_uri_reference
46 : return a `boost::system::result` containing either a valid
47 : @ref url_view upon success, otherwise they
48 : contain an error. The error can be converted to
49 : an exception by the caller if desired:
50 : @code
51 : system::result< url_view > rv = parse_uri_reference( "https://www.example.com/index.htm?text=none#a1" );
52 : @endcode
53 :
54 : @par BNF
55 : @code
56 : URI-reference = URI / relative-ref
57 :
58 : URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
59 :
60 : relative-ref = relative-part [ "?" query ] [ "#" fragment ]
61 : @endcode
62 :
63 : @par Specification
64 : @li <a href="https://tools.ietf.org/html/rfc3986"
65 : >Uniform Resource Identifier (URI): Generic Syntax (rfc3986)</a>
66 :
67 : @see
68 : @ref parse_absolute_uri,
69 : @ref parse_origin_form,
70 : @ref parse_relative_ref,
71 : @ref parse_uri,
72 : @ref parse_uri_reference.
73 : */
74 : class BOOST_URL_DECL url_view
75 : : public url_view_base
76 : {
77 : friend std::hash<url_view>;
78 : friend class url_view_base;
79 : friend class params_base;
80 : friend class params_encoded_base;
81 :
82 : #ifndef BOOST_URL_DOCS
83 : // VFALCO docca emits this erroneously
84 : friend struct detail::url_impl;
85 : #endif
86 :
87 : using url_view_base::digest;
88 :
89 : explicit
90 3573 : url_view(
91 : detail::url_impl const& impl) noexcept
92 3573 : : url_view_base(impl)
93 : {
94 3573 : }
95 :
96 : public:
97 : //--------------------------------------------
98 : //
99 : // Special Members
100 : //
101 : //--------------------------------------------
102 :
103 : /** Destructor
104 :
105 : Any params, segments, iterators, or
106 : other views which reference the same
107 : underlying character buffer remain
108 : valid.
109 : */
110 : ~url_view() = default;
111 :
112 : /** Constructor
113 :
114 : Default constructed views refer to
115 : a string with zero length, which
116 : always remains valid. This matches
117 : the grammar for a relative-ref with
118 : an empty path and no query or
119 : fragment.
120 :
121 : @par Example
122 : @code
123 : url_view u;
124 : @endcode
125 :
126 : @par Postconditions
127 : @code
128 : this->empty() == true
129 : @endcode
130 :
131 : @par Complexity
132 : Constant.
133 :
134 : @par Exception Safety
135 : Throws nothing.
136 :
137 : @par BNF
138 : @code
139 : relative-ref = relative-part [ "?" query ] [ "#" fragment ]
140 : @endcode
141 :
142 : @par Specification
143 : <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.2"
144 : >4.2. Relative Reference (rfc3986)</a>
145 : */
146 : url_view() noexcept;
147 :
148 : /** Constructor
149 :
150 : This function constructs a URL from
151 : the string `s`, which must contain a
152 : valid <em>URI</em> or <em>relative-ref</em>
153 : or else an exception is thrown. Upon
154 : successful construction, the view
155 : refers to the characters in the
156 : buffer pointed to by `s`.
157 : Ownership is not transferred; The caller
158 : is responsible for ensuring that the
159 : lifetime of the buffer extends until
160 : it is no longer referenced.
161 :
162 : @par Example
163 : @code
164 : url_view u( "http://www.example.com/index.htm" );
165 : @endcode
166 :
167 : @par Effects
168 : @code
169 : return parse_uri_reference( s ).value();
170 : @endcode
171 :
172 : @par Complexity
173 : Linear in `s.size()`.
174 :
175 : @par Exception Safety
176 : Exceptions thrown on invalid input.
177 :
178 : @throw system_error
179 : The input failed to parse correctly.
180 :
181 : @param s The string to parse.
182 :
183 : @par BNF
184 : @code
185 : URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
186 :
187 : relative-ref = relative-part [ "?" query ] [ "#" fragment ]
188 : @endcode
189 :
190 : @par Specification
191 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.1"
192 : >4.1. URI Reference</a>
193 :
194 : @see
195 : @ref parse_uri_reference.
196 : */
197 : url_view(core::string_view s);
198 :
199 : /// @copydoc url_view(core::string_view)
200 : template<
201 : class String
202 : #ifndef BOOST_URL_DOCS
203 : , class = typename std::enable_if<
204 : std::is_convertible<
205 : String,
206 : core::string_view
207 : >::value &&
208 : !std::is_convertible<
209 : String*,
210 : url_view_base*
211 : >::value
212 : >::type
213 : #endif
214 : >
215 223 : url_view(
216 : String const& s)
217 : : url_view(
218 223 : detail::to_sv(s))
219 : {
220 222 : }
221 :
222 : /** Constructor
223 :
224 : After construction, both views
225 : reference the same underlying character
226 : buffer. Ownership is not transferred.
227 :
228 : @par Postconditions
229 : @code
230 : this->buffer().data() == other.buffer().data()
231 : @endcode
232 :
233 : @par Complexity
234 : Constant.
235 :
236 : @par Exception Safety
237 : Throws nothing.
238 :
239 : @param other The other view.
240 : */
241 15770 : url_view(
242 : url_view const& other) noexcept
243 15770 : : url_view(static_cast<
244 15770 : url_view_base const&>(other))
245 : {
246 15770 : }
247 :
248 : /** Constructor
249 :
250 : After construction, both views
251 : reference the same underlying character
252 : buffer. Ownership is not transferred.
253 :
254 : @par Postconditions
255 : @code
256 : this->buffer().data() == other.buffer().data()
257 : @endcode
258 :
259 : @par Complexity
260 : Constant.
261 :
262 : @par Exception Safety
263 : Throws nothing.
264 :
265 : @param other The other view.
266 : */
267 : url_view(
268 : url_view_base const& other) noexcept;
269 :
270 : /** Assignment
271 :
272 : After assignment, both views
273 : reference the same underlying character
274 : buffer. Ownership is not transferred.
275 :
276 : @par Postconditions
277 : @code
278 : this->buffer().data() == other.buffer().data()
279 : @endcode
280 :
281 : @par Complexity
282 : Constant.
283 :
284 : @par Exception Safety
285 : Throws nothing.
286 :
287 : @param other The other view.
288 : @return A reference to this object.
289 : */
290 : url_view&
291 13 : operator=(
292 : url_view const& other) noexcept
293 : {
294 13 : if (this != &other)
295 : *this = static_cast<
296 12 : url_view_base const&>(other);
297 13 : return *this;
298 : }
299 :
300 : /** Assignment
301 :
302 : After assignment, both views
303 : reference the same underlying character
304 : buffer. Ownership is not transferred.
305 :
306 : @par Postconditions
307 : @code
308 : this->buffer().data() == other.buffer().data()
309 : @endcode
310 :
311 : @par Complexity
312 : Constant.
313 :
314 : @par Exception Safety
315 : Throws nothing.
316 :
317 : @param other The other view.
318 : @return A reference to this object.
319 : */
320 : url_view& operator=(
321 : url_view_base const& other) noexcept;
322 :
323 : //--------------------------------------------
324 : //
325 : // Observers
326 : //
327 : //--------------------------------------------
328 :
329 : /** Return the maximum number of characters possible
330 :
331 : This represents the largest number of
332 : characters that are possible in a url,
333 : not including any null terminator.
334 :
335 : @par Complexity
336 : Constant.
337 :
338 : @par Exception Safety
339 : Throws nothing.
340 :
341 : @return The maximum number of characters possible.
342 : */
343 : static
344 : constexpr
345 : std::size_t
346 : max_size() noexcept
347 : {
348 : return BOOST_URL_MAX_SIZE;
349 : }
350 : };
351 :
352 : } // urls
353 : } // boost
354 :
355 : //------------------------------------------------
356 :
357 : // std::hash specialization
358 : #ifndef BOOST_URL_DOCS
359 : namespace std {
360 : template<>
361 : struct hash< ::boost::urls::url_view >
362 : {
363 : hash() = default;
364 : hash(hash const&) = default;
365 : hash& operator=(hash const&) = default;
366 :
367 : explicit
368 76 : hash(std::size_t salt) noexcept
369 76 : : salt_(salt)
370 : {
371 76 : }
372 :
373 : std::size_t
374 304 : operator()(::boost::urls::url_view const& u) const noexcept
375 : {
376 304 : return u.digest(salt_);
377 : }
378 :
379 : private:
380 : std::size_t salt_ = 0;
381 : };
382 : } // std
383 : #endif
384 :
385 : #endif
|