Line | Branch | Exec | Source |
---|---|---|---|
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 @ref result containing either a valid | ||
47 | @ref url_view upon succcess, 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 | 31 | 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 | 3497 | url_view( | |
91 | detail::url_impl const& impl) noexcept | ||
92 | 3497 | : url_view_base(impl) | |
93 | { | ||
94 | 3497 | } | |
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 | 426 | url_view( | |
216 | String const& s) | ||
217 | : url_view( | ||
218 | 426 | detail::to_sv(s)) | |
219 | { | ||
220 | 424 | } | |
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 | 15416 | url_view( | |
240 | url_view const& other) noexcept | ||
241 | 15416 | : url_view(static_cast< | |
242 | 15416 | url_view_base const&>(other)) | |
243 | { | ||
244 | 15416 | } | |
245 | |||
246 | /** Constructor | ||
247 | |||
248 | After construction, both views | ||
249 | reference the same underlying character | ||
250 | buffer. Ownership is not transferred. | ||
251 | |||
252 | @par Postconditions | ||
253 | @code | ||
254 | this->buffer().data() == other.buffer().data() | ||
255 | @endcode | ||
256 | |||
257 | @par Complexity | ||
258 | Constant. | ||
259 | |||
260 | @par Exception Safety | ||
261 | Throws nothing. | ||
262 | */ | ||
263 | url_view( | ||
264 | url_view_base const& other) noexcept; | ||
265 | |||
266 | /** Assignment | ||
267 | |||
268 | After assignment, both views | ||
269 | reference the same underlying character | ||
270 | buffer. Ownership is not transferred. | ||
271 | |||
272 | @par Postconditions | ||
273 | @code | ||
274 | this->buffer().data() == other.buffer().data() | ||
275 | @endcode | ||
276 | |||
277 | @par Complexity | ||
278 | Constant. | ||
279 | |||
280 | @par Exception Safety | ||
281 | Throws nothing. | ||
282 | */ | ||
283 | url_view& | ||
284 | 13 | operator=( | |
285 | url_view const& other) noexcept | ||
286 | { | ||
287 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1 times.
|
13 | if (this != &other) |
288 | *this = static_cast< | ||
289 | 12 | url_view_base const&>(other); | |
290 | 13 | return *this; | |
291 | } | ||
292 | |||
293 | /** Assignment | ||
294 | |||
295 | After assignment, both views | ||
296 | reference the same underlying character | ||
297 | buffer. Ownership is not transferred. | ||
298 | |||
299 | @par Postconditions | ||
300 | @code | ||
301 | this->buffer().data() == other.buffer().data() | ||
302 | @endcode | ||
303 | |||
304 | @par Complexity | ||
305 | Constant. | ||
306 | |||
307 | @par Exception Safety | ||
308 | Throws nothing. | ||
309 | */ | ||
310 | url_view& operator=( | ||
311 | url_view_base const& other) noexcept; | ||
312 | |||
313 | //-------------------------------------------- | ||
314 | // | ||
315 | // Observers | ||
316 | // | ||
317 | //-------------------------------------------- | ||
318 | |||
319 | /** Return the maximum number of characters possible | ||
320 | |||
321 | This represents the largest number of | ||
322 | characters that are possible in a url, | ||
323 | not including any null terminator. | ||
324 | |||
325 | @par Complexity | ||
326 | Constant. | ||
327 | |||
328 | @par Exception Safety | ||
329 | Throws nothing. | ||
330 | */ | ||
331 | static | ||
332 | constexpr | ||
333 | std::size_t | ||
334 | max_size() noexcept | ||
335 | { | ||
336 | return BOOST_URL_MAX_SIZE; | ||
337 | } | ||
338 | }; | ||
339 | |||
340 | } // urls | ||
341 | } // boost | ||
342 | |||
343 | //------------------------------------------------ | ||
344 | |||
345 | // std::hash specialization | ||
346 | #ifndef BOOST_URL_DOCS | ||
347 | namespace std { | ||
348 | template<> | ||
349 | struct hash< ::boost::urls::url_view > | ||
350 | { | ||
351 | hash() = default; | ||
352 | hash(hash const&) = default; | ||
353 | hash& operator=(hash const&) = default; | ||
354 | |||
355 | explicit | ||
356 | 69 | hash(std::size_t salt) noexcept | |
357 | 69 | : salt_(salt) | |
358 | { | ||
359 | 69 | } | |
360 | |||
361 | std::size_t | ||
362 | 276 | operator()(::boost::urls::url_view const& u) const noexcept | |
363 | { | ||
364 | 276 | return u.digest(salt_); | |
365 | } | ||
366 | |||
367 | private: | ||
368 | std::size_t salt_ = 0; | ||
369 | }; | ||
370 | } // std | ||
371 | #endif | ||
372 | |||
373 | #endif | ||
374 |