GCC Code Coverage Report


Directory: libs/url/
File: boost/url/url.hpp
Date: 2024-03-05 20:06:57
Exec Total Coverage
Lines: 57 57 100.0%
Functions: 46 46 100.0%
Branches: 1 2 50.0%

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_HPP
12 #define BOOST_URL_URL_HPP
13
14 #include <boost/url/detail/config.hpp>
15 #include <boost/url/url_base.hpp>
16 #include <boost/assert.hpp>
17 #include <utility>
18
19 namespace boost {
20 namespace urls {
21
22 /** A modifiable container for a URL.
23
24 This container owns a url, represented
25 by a null-terminated character buffer
26 which is managed by performing dymamic
27 memory allocations as needed.
28 The contents may be inspected and modified,
29 and the implementation maintains a useful
30 invariant: changes to the url always
31 leave it in a valid state.
32
33 @par Exception Safety
34
35 @li Functions marked `noexcept` provide the
36 no-throw guarantee, otherwise:
37
38 @li Functions which throw offer the strong
39 exception safety guarantee.
40
41 @par BNF
42 @code
43 URI-reference = URI / relative-ref
44
45 URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
46
47 relative-ref = relative-part [ "?" query ] [ "#" fragment ]
48
49 absolute-URI = scheme ":" hier-part [ "?" query ]
50 @endcode
51
52 @par Specification
53 @li <a href="https://tools.ietf.org/html/rfc3986"
54 >Uniform Resource Identifier (URI): Generic Syntax (rfc3986)</a>
55
56 @see
57 @ref parse_absolute_uri,
58 @ref parse_relative_ref,
59 @ref parse_uri,
60 @ref parse_uri_reference,
61 @ref resolve.
62 */
63 1088 class BOOST_URL_DECL url
64 : public url_base
65 {
66 friend std::hash<url>;
67
68 using url_view_base::digest;
69
70 public:
71 //--------------------------------------------
72 //
73 // Special Members
74 //
75 //--------------------------------------------
76
77 /** Destructor
78
79 Any params, segments, iterators, or
80 views which reference this object are
81 invalidated. The underlying character
82 buffer is destroyed, invalidating all
83 references to it.
84 */
85 virtual ~url();
86
87 /** Constructor
88
89 Default constructed urls contain
90 a zero-length string. This matches
91 the grammar for a relative-ref with
92 an empty path and no query or
93 fragment.
94
95 @par Example
96 @code
97 url u;
98 @endcode
99
100 @par Postconditions
101 @code
102 this->empty() == true
103 @endcode
104
105 @par Complexity
106 Constant.
107
108 @par Exception Safety
109 Throws nothing.
110
111 @par BNF
112 @code
113 relative-ref = relative-part [ "?" query ] [ "#" fragment ]
114 @endcode
115
116 @par Specification
117 <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.2"
118 >4.2. Relative Reference (rfc3986)</a>
119 */
120 url() noexcept;
121
122 /** Constructor
123
124 This function constructs a URL from
125 the string `s`, which must contain a
126 valid <em>URI</em> or <em>relative-ref</em>
127 or else an exception is thrown.
128 The new url retains ownership by
129 allocating a copy of the passed string.
130
131 @par Example
132 @code
133 url u( "https://www.example.com" );
134 @endcode
135
136 @par Effects
137 @code
138 return url( parse_uri_reference( s ).value() );
139 @endcode
140
141 @par Postconditions
142 @code
143 this->buffer().data() != s.data()
144 @endcode
145
146 @par Complexity
147 Linear in `s.size()`.
148
149 @par Exception Safety
150 Calls to allocate may throw.
151 Exceptions thrown on invalid input.
152
153 @throw system_error
154 The input does not contain a valid url.
155
156 @param s The string to parse.
157
158 @par BNF
159 @code
160 URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
161
162 relative-ref = relative-part [ "?" query ] [ "#" fragment ]
163 @endcode
164
165 @par Specification
166 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.1"
167 >4.1. URI Reference</a>
168 */
169 explicit
170 url(core::string_view s);
171
172 /** Constructor
173
174 The contents of `u` are transferred
175 to the newly constructed object,
176 which includes the underlying
177 character buffer.
178 After construction, the moved-from
179 object is as if default constructed.
180
181 @par Postconditions
182 @code
183 u.empty() == true
184 @endcode
185
186 @par Complexity
187 Constant.
188
189 @par Exception Safety
190 Throws nothing.
191
192 @param u The url to move from.
193 */
194 url(url&& u) noexcept;
195
196 /** Constructor
197
198 The newly constructed object
199 contains a copy of `u`.
200
201 @par Postconditions
202 @code
203 this->buffer() == u.buffer() && this->buffer().data() != u.buffer().data()
204 @endcode
205
206 @par Complexity
207 Linear in `u.size()`.
208
209 @par Exception Safety
210 Strong guarantee.
211 Calls to allocate may throw.
212
213 @throw std::length_error `u.size() > max_size()`.
214
215 @param u The url to copy.
216 */
217 2937 url(url_view_base const& u)
218 2937 {
219
1/2
✓ Branch 1 taken 2937 times.
✗ Branch 2 not taken.
2937 copy(u);
220 2937 }
221
222 /** Constructor
223
224 The newly constructed object
225 contains a copy of `u`.
226
227 @par Postconditions
228 @code
229 this->buffer() == u.buffer() && this->buffer().data() != u.buffer().data()
230 @endcode
231
232 @par Complexity
233 Linear in `u.size()`.
234
235 @par Exception Safety
236 Strong guarantee.
237 Calls to allocate may throw.
238
239 @throw std::length_error `u.size() > max_size()`.
240
241 @param u The url to copy.
242 */
243 257 url(url const& u)
244 257 : url(static_cast<
245 257 url_view_base const&>(u))
246 {
247 257 }
248
249 /** Assignment
250
251 The contents of `u` are transferred to
252 `this`, including the underlying
253 character buffer. The previous contents
254 of `this` are destroyed.
255 After assignment, the moved-from
256 object is as if default constructed.
257
258 @par Postconditions
259 @code
260 u.empty() == true
261 @endcode
262
263 @par Complexity
264 Constant.
265
266 @par Exception Safety
267 Throws nothing.
268
269 @param u The url to assign from.
270 */
271 url&
272 operator=(url&& u) noexcept;
273
274 /** Assignment
275
276 The contents of `u` are copied and
277 the previous contents of `this` are
278 destroyed.
279 Capacity is preserved, or increases.
280
281 @par Postconditions
282 @code
283 this->buffer() == u.buffer() && this->buffer().data() != u.buffer().data()
284 @endcode
285
286 @par Complexity
287 Linear in `u.size()`.
288
289 @par Exception Safety
290 Strong guarantee.
291 Calls to allocate may throw.
292
293 @throw std::length_error `u.size() > max_size()`.
294
295 @param u The url to copy.
296 */
297 url&
298 99 operator=(
299 url_view_base const& u)
300 {
301 99 copy(u);
302 99 return *this;
303 }
304
305 /** Assignment
306
307 The contents of `u` are copied and
308 the previous contents of `this` are
309 destroyed.
310 Capacity is preserved, or increases.
311
312 @par Postconditions
313 @code
314 this->buffer() == u.buffer() && this->buffer().data() != u.buffer().data()
315 @endcode
316
317 @par Complexity
318 Linear in `u.size()`.
319
320 @par Exception Safety
321 Strong guarantee.
322 Calls to allocate may throw.
323
324 @param u The url to copy.
325 */
326 url&
327 1 operator=(url const& u)
328 {
329 return (*this)=static_cast<
330 1 url_view_base const&>(u);
331 }
332
333 //--------------------------------------------
334
335 /** Swap the contents.
336
337 Exchanges the contents of this url with another
338 url. All views, iterators and references remain valid.
339
340 If `this == &other`, this function call has no effect.
341
342 @par Example
343 @code
344 url u1( "https://www.example.com" );
345 url u2( "https://www.boost.org" );
346 u1.swap(u2);
347 assert(u1 == "https://www.boost.org" );
348 assert(u2 == "https://www.example.com" );
349 @endcode
350
351 @par Complexity
352 Constant
353
354 @par Exception Safety
355 Throws nothing.
356
357 @param other The object to swap with
358
359 */
360 void
361 swap(url& other) noexcept;
362
363 /** Swap
364
365 Exchanges the contents of `v0` with another `v1`.
366 All views, iterators and references remain
367 valid.
368
369 If `&v0 == &v1`, this function call has no effect.
370
371 @par Example
372 @code
373 url u1( "https://www.example.com" );
374 url u2( "https://www.boost.org" );
375 std::swap(u1, u2);
376 assert(u1 == "https://www.boost.org" );
377 assert(u2 == "https://www.example.com" );
378 @endcode
379
380 @par Effects
381 @code
382 v0.swap( v1 );
383 @endcode
384
385 @par Complexity
386 Constant
387
388 @par Exception Safety
389 Throws nothing
390
391 @param v0, v1 The objects to swap
392
393 @see
394 @ref url::swap
395 */
396 friend
397 void
398 2 swap(url& v0, url& v1) noexcept
399 {
400 2 v0.swap(v1);
401 2 }
402
403 //--------------------------------------------
404 //
405 // fluent api
406 //
407
408 /// @copydoc url_base::set_scheme
409 51 url& set_scheme(core::string_view s) { url_base::set_scheme(s); return *this; }
410 /// @copydoc url_base::set_scheme_id
411 11 url& set_scheme_id(urls::scheme id) { url_base::set_scheme_id(id); return *this; }
412 /// @copydoc url_base::remove_scheme
413 21 url& remove_scheme() { url_base::remove_scheme(); return *this; }
414
415 /// @copydoc url_base::set_encoded_authority
416 41 url& set_encoded_authority(pct_string_view s) { url_base::set_encoded_authority(s); return *this; }
417 /// @copydoc url_base::remove_authority
418 43 url& remove_authority() { url_base::remove_authority(); return *this; }
419
420 /// @copydoc url_base::set_userinfo
421 45 url& set_userinfo(core::string_view s) { url_base::set_userinfo(s); return *this; }
422 /// @copydoc url_base::set_encoded_userinfo
423 51 url& set_encoded_userinfo(pct_string_view s) { url_base::set_encoded_userinfo(s); return *this; }
424 /// @copydoc url_base::remove_userinfo
425 22 url& remove_userinfo() noexcept { url_base::remove_userinfo(); return *this; }
426 /// @copydoc url_base::set_user
427 1 url& set_user(core::string_view s) { url_base::set_user(s); return *this; }
428 /// @copydoc url_base::set_encoded_user
429 17 url& set_encoded_user(pct_string_view s) { url_base::set_encoded_user(s); return *this; }
430 /// @copydoc url_base::set_password
431 35 url& set_password(core::string_view s) { url_base::set_password(s); return *this; }
432 /// @copydoc url_base::set_encoded_password
433 38 url& set_encoded_password(pct_string_view s) { url_base::set_encoded_password(s); return *this; }
434 /// @copydoc url_base::remove_password
435 19 url& remove_password() noexcept { url_base::remove_password(); return *this; }
436
437 /// @copydoc url_base::set_host
438 12 url& set_host(core::string_view s) { url_base::set_host(s); return *this; }
439 /// @copydoc url_base::set_encoded_host
440 114 url& set_encoded_host(pct_string_view s) { url_base::set_encoded_host(s); return *this; }
441 /// @copydoc url_base::set_host_address
442 9 url& set_host_address(core::string_view s) { url_base::set_host_address(s); return *this; }
443 /// @copydoc url_base::set_encoded_host_address
444 7 url& set_encoded_host_address(pct_string_view s) { url_base::set_encoded_host_address(s); return *this; }
445 /// @copydoc url_base::set_host_ipv4
446 4 url& set_host_ipv4(ipv4_address const& addr) { url_base::set_host_ipv4(addr); return *this; }
447 /// @copydoc url_base::set_host_ipv6
448 2 url& set_host_ipv6(ipv6_address const& addr) { url_base::set_host_ipv6(addr); return *this; }
449 /// @copydoc url_base::set_host_ipvfuture
450 3 url& set_host_ipvfuture(core::string_view s) { url_base::set_host_ipvfuture(s); return *this; }
451 /// @copydoc url_base::set_host_name
452 4 url& set_host_name(core::string_view s) { url_base::set_host_name(s); return *this; }
453 /// @copydoc url_base::set_encoded_host_name
454 4 url& set_encoded_host_name(pct_string_view s) { url_base::set_encoded_host_name(s); return *this; }
455 /// @copydoc url_base::set_port_number
456 23 url& set_port_number(std::uint16_t n) { url_base::set_port_number(n); return *this; }
457 /// @copydoc url_base::set_port
458 89 url& set_port(core::string_view s) { url_base::set_port(s); return *this; }
459 /// @copydoc url_base::remove_port
460 25 url& remove_port() noexcept { url_base::remove_port(); return *this; }
461
462 /// @copydoc url_base::set_path_absolute
463 //bool set_path_absolute(bool absolute);
464 /// @copydoc url_base::set_path
465 23 url& set_path(core::string_view s) { url_base::set_path(s); return *this; }
466 /// @copydoc url_base::set_encoded_path
467 57 url& set_encoded_path(pct_string_view s) { url_base::set_encoded_path(s); return *this; }
468
469 /// @copydoc url_base::set_query
470 9 url& set_query(core::string_view s) { url_base::set_query(s); return *this; }
471 /// @copydoc url_base::set_encoded_query
472 18 url& set_encoded_query(pct_string_view s) { url_base::set_encoded_query(s); return *this; }
473 /// @copydoc url_base::set_params
474 1 url& set_params(std::initializer_list<param_view> ps) { url_base::set_params(ps); return *this; }
475 /// @copydoc url_base::set_encoded_params
476 1 url& set_encoded_params(std::initializer_list< param_pct_view > ps) { url_base::set_encoded_params(ps); return *this; }
477 /// @copydoc url_base::remove_query
478 6 url& remove_query() noexcept { url_base::remove_query(); return *this; }
479
480 /// @copydoc url_base::remove_fragment
481 4 url& remove_fragment() noexcept { url_base::remove_fragment(); return *this; }
482 /// @copydoc url_base::set_fragment
483 5 url& set_fragment(core::string_view s) { url_base::set_fragment(s); return *this; }
484 /// @copydoc url_base::set_encoded_fragment
485 21 url& set_encoded_fragment(pct_string_view s) { url_base::set_encoded_fragment(s); return *this; }
486
487 /// @copydoc url_base::remove_origin
488 14 url& remove_origin() { url_base::remove_origin(); return *this; }
489
490 /// @copydoc url_base::normalize
491 35 url& normalize() { url_base::normalize(); return *this; }
492 /// @copydoc url_base::normalize_scheme
493 2 url& normalize_scheme() { url_base::normalize_scheme(); return *this; }
494 /// @copydoc url_base::normalize_authority
495 347 url& normalize_authority() { url_base::normalize_authority(); return *this; }
496 /// @copydoc url_base::normalize_path
497 367 url& normalize_path() { url_base::normalize_path(); return *this; }
498 /// @copydoc url_base::normalize_query
499 url& normalize_query() { url_base::normalize_query(); return *this; }
500 /// @copydoc url_base::normalize_fragment
501 url& normalize_fragment() { url_base::normalize_fragment(); return *this; }
502
503 //--------------------------------------------
504
505 private:
506 char* allocate(std::size_t);
507 void deallocate(char* s);
508
509 void clear_impl() noexcept override;
510 void reserve_impl(std::size_t, op_t&) override;
511 void cleanup(op_t&) override;
512 };
513
514 } // urls
515 } // boost
516
517 //------------------------------------------------
518
519 // std::hash specialization
520 #ifndef BOOST_URL_DOCS
521 namespace std {
522 template<>
523 struct hash< ::boost::urls::url >
524 {
525 hash() = default;
526 hash(hash const&) = default;
527 hash& operator=(hash const&) = default;
528
529 explicit
530 hash(std::size_t salt) noexcept
531 : salt_(salt)
532 {
533 }
534
535 std::size_t
536 operator()(::boost::urls::url const& u) const noexcept
537 {
538 return u.digest(salt_);
539 }
540
541 private:
542 std::size_t salt_ = 0;
543 };
544 } // std
545 #endif
546
547 #endif
548