GCC Code Coverage Report


Directory: libs/url/
File: boost/url/static_url.hpp
Date: 2024-03-05 20:06:57
Exec Total Coverage
Lines: 18 22 81.8%
Functions: 29 32 90.6%
Branches: 2 2 100.0%

Line Branch Exec Source
1 //
2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/url
8 //
9
10 #ifndef BOOST_URL_STATIC_URL_HPP
11 #define BOOST_URL_STATIC_URL_HPP
12
13 #include <boost/url/detail/config.hpp>
14 #include <boost/url/url_base.hpp>
15 #include <boost/align/align_up.hpp>
16 #include <boost/static_assert.hpp>
17 #include <cstddef>
18
19 namespace boost {
20 namespace urls {
21
22 #ifndef BOOST_URL_DOCS
23 template<std::size_t Capacity>
24 class static_url;
25 #endif
26
27 // VFALCO This class is for reducing
28 // the number of template instantiations,
29 // and keep definitions in the library
30
31 /** Common implementation for all static URLs
32
33 This base class is used by the library
34 to provide common functionality for
35 static URLs. Users should not use this
36 class directly. Instead, construct an
37 instance of one of the containers
38 or call a parsing function.
39
40 @par Containers
41 @li @ref url
42 @li @ref url_view
43 @li @ref static_url
44
45 @par Parsing Functions
46 @li @ref parse_absolute_uri
47 @li @ref parse_origin_form
48 @li @ref parse_relative_ref
49 @li @ref parse_uri
50 @li @ref parse_uri_reference
51 */
52 class BOOST_URL_DECL
53 static_url_base
54 : public url_base
55 {
56 template<std::size_t>
57 friend class static_url;
58
59 58 ~static_url_base() = default;
60 static_url_base(
61 char* buf, std::size_t cap) noexcept;
62 static_url_base(
63 char* buf, std::size_t cap, core::string_view s);
64 void clear_impl() noexcept override;
65 void reserve_impl(std::size_t, op_t&) override;
66 void cleanup(op_t&) override;
67
68 void
69 24 copy(url_view_base const& u)
70 {
71 24 this->url_base::copy(u);
72 21 }
73
74 };
75
76 //------------------------------------------------
77
78 /** A modifiable container for a URL.
79
80 This container owns a url, represented
81 by an inline, null-terminated character
82 buffer with fixed capacity.
83 The contents may be inspected and modified,
84 and the implementation maintains a useful
85 invariant: changes to the url always
86 leave it in a valid state.
87
88 @par Example
89 @code
90 static_url< 1024 > u( "https://www.example.com" );
91 @endcode
92
93 @par Invariants
94 @code
95 this->capacity() == Capacity
96 @endcode
97
98 @tparam Capacity The maximum capacity
99 in characters, not including the
100 null terminator.
101
102 @see
103 @ref url,
104 @ref url_view.
105 */
106 template<std::size_t Capacity>
107 class static_url
108 : public static_url_base
109 {
110 char buf_[Capacity + 1];
111
112 friend std::hash<static_url>;
113 using url_view_base::digest;
114
115 public:
116 //--------------------------------------------
117 //
118 // Special Members
119 //
120 //--------------------------------------------
121
122 /** Destructor
123
124 Any params, segments, iterators, or
125 views which reference this object are
126 invalidated. The underlying character
127 buffer is destroyed, invalidating all
128 references to it.
129 */
130 54 ~static_url() = default;
131
132 /** Constructor
133
134 Default constructed urls contain
135 a zero-length string. This matches
136 the grammar for a relative-ref with
137 an empty path and no query or
138 fragment.
139
140 @par Example
141 @code
142 static_url< 1024 > u;
143 @endcode
144
145 @par Postconditions
146 @code
147 this->empty() == true
148 @endcode
149
150 @par Complexity
151 Constant.
152
153 @par Exception Safety
154 Throws nothing.
155
156 @par BNF
157 @code
158 relative-ref = relative-part [ "?" query ] [ "#" fragment ]
159 @endcode
160
161 @par Specification
162 <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.2"
163 >4.2. Relative Reference (rfc3986)</a>
164 */
165 28 static_url() noexcept
166 : static_url_base(
167 28 buf_, sizeof(buf_))
168 {
169 28 }
170
171 /** Constructor
172
173 This function constructs a url from
174 the string `s`, which must contain a
175 valid <em>URI</em> or <em>relative-ref</em>
176 or else an exception is thrown.
177 The new url retains ownership by
178 making a copy of the passed string.
179
180 @par Example
181 @code
182 static_url< 1024 > u( "https://www.example.com" );
183 @endcode
184
185 @par Effects
186 @code
187 return static_url( parse_uri_reference( s ).value() );
188 @endcode
189
190 @par Postconditions
191 @code
192 this->buffer().data() != s.data()
193 @endcode
194
195 @par Complexity
196 Linear in `s.size()`.
197
198 @par Exception Safety
199 Exceptions thrown on invalid input.
200
201 @throw system_error
202 The input does not contain a valid url.
203
204 @param s The string to parse.
205
206 @par BNF
207 @code
208 URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
209
210 relative-ref = relative-part [ "?" query ] [ "#" fragment ]
211 @endcode
212
213 @par Specification
214 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.1"
215 >4.1. URI Reference</a>
216 */
217 explicit
218 30 static_url(
219 core::string_view s)
220 : static_url_base(
221 30 buf_, sizeof(buf_), s)
222 {
223 26 }
224
225 /** Constructor
226
227 The newly constructed object contains
228 a copy of `u`.
229
230 @par Postconditions
231 @code
232 this->buffer() == u.buffer() && this->buffer.data() != u.buffer().data()
233 @endcode
234
235 @par Complexity
236 Linear in `u.size()`.
237
238 @par Exception Safety
239 Exception thrown if maximum size exceeded.
240
241 @param u The url to copy.
242 */
243 static_url(
244 static_url const& u) noexcept
245 : static_url()
246 {
247 copy(u);
248 }
249
250 /** Constructor
251
252 The newly constructed object contains
253 a copy of `u`.
254
255 @par Postconditions
256 @code
257 this->buffer() == u.buffer() && this->buffer.data() != u.buffer().data()
258 @endcode
259
260 @par Complexity
261 Linear in `u.size()`.
262
263 @par Exception Safety
264 Exception thrown if capacity exceeded.
265
266 @throw system_error
267 Capacity would be exceeded.
268
269 @param u The url to copy.
270 */
271 10 static_url(
272 url_view_base const& u)
273 12 : static_url()
274 {
275
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
10 copy(u);
276 8 }
277
278 /** Assignment
279
280 The contents of `u` are copied and
281 the previous contents of `this` are
282 discarded.
283 Capacity remains unchanged.
284
285 @par Postconditions
286 @code
287 this->buffer() == u.buffer() && this->buffer().data() != u.buffer().data()
288 @endcode
289
290 @par Complexity
291 Linear in `u.size()`.
292
293 @par Exception Safety
294 Throws nothing.
295
296 @param u The url to copy.
297 */
298 static_url&
299 operator=(
300 static_url const& u) noexcept
301 {
302 if (this != &u)
303 copy(u);
304 return *this;
305 }
306
307 /** Assignment
308
309 The contents of `u` are copied and
310 the previous contents of `this` are
311 discarded.
312
313 @par Postconditions
314 @code
315 this->buffer() == u.buffer() && this->buffer().data() != u.buffer().data()
316 @endcode
317
318 @par Complexity
319 Linear in `u.size()`.
320
321 @par Exception Safety
322 Strong guarantee.
323 Exception thrown if capacity exceeded.
324
325 @throw system_error
326 Capacity would be exceeded.
327
328 @param u The url to copy.
329 */
330 static_url&
331 5 operator=(
332 url_view_base const& u)
333 {
334 5 copy(u);
335 4 return *this;
336 }
337
338
339 //--------------------------------------------
340 //
341 // fluent api
342 //
343
344 /// @copydoc url_base::set_scheme
345 static_url& set_scheme(core::string_view s) { url_base::set_scheme(s); return *this; }
346 /// @copydoc url_base::set_scheme_id
347 static_url& set_scheme_id(urls::scheme id) { url_base::set_scheme_id(id); return *this; }
348 /// @copydoc url_base::remove_scheme
349 static_url& remove_scheme() { url_base::remove_scheme(); return *this; }
350
351 /// @copydoc url_base::set_encoded_authority
352 static_url& set_encoded_authority(pct_string_view s) { url_base::set_encoded_authority(s); return *this; }
353 /// @copydoc url_base::remove_authority
354 static_url& remove_authority() { url_base::remove_authority(); return *this; }
355
356 /// @copydoc url_base::set_userinfo
357 static_url& set_userinfo(core::string_view s) { url_base::set_userinfo(s); return *this; }
358 /// @copydoc url_base::set_encoded_userinfo
359 static_url& set_encoded_userinfo(pct_string_view s) { url_base::set_encoded_userinfo(s); return *this; }
360 /// @copydoc url_base::remove_userinfo
361 static_url& remove_userinfo() noexcept { url_base::remove_userinfo(); return *this; }
362 /// @copydoc url_base::set_user
363 static_url& set_user(core::string_view s) { url_base::set_user(s); return *this; }
364 /// @copydoc url_base::set_encoded_user
365 static_url& set_encoded_user(pct_string_view s) { url_base::set_encoded_user(s); return *this; }
366 /// @copydoc url_base::set_password
367 static_url& set_password(core::string_view s) { url_base::set_password(s); return *this; }
368 /// @copydoc url_base::set_encoded_password
369 static_url& set_encoded_password(pct_string_view s) { url_base::set_encoded_password(s); return *this; }
370 /// @copydoc url_base::remove_password
371 static_url& remove_password() noexcept { url_base::remove_password(); return *this; }
372
373 /// @copydoc url_base::set_host
374 static_url& set_host(core::string_view s) { url_base::set_host(s); return *this; }
375 /// @copydoc url_base::set_encoded_host
376 static_url& set_encoded_host(pct_string_view s) { url_base::set_encoded_host(s); return *this; }
377 /// @copydoc url_base::set_host_address
378 static_url& set_host_address(core::string_view s) { url_base::set_host_address(s); return *this; }
379 /// @copydoc url_base::set_encoded_host_address
380 static_url& set_encoded_host_address(pct_string_view s) { url_base::set_encoded_host_address(s); return *this; }
381 /// @copydoc url_base::set_host_ipv4
382 static_url& set_host_ipv4(ipv4_address const& addr) { url_base::set_host_ipv4(addr); return *this; }
383 /// @copydoc url_base::set_host_ipv6
384 static_url& set_host_ipv6(ipv6_address const& addr) { url_base::set_host_ipv6(addr); return *this; }
385 /// @copydoc url_base::set_host_ipvfuture
386 static_url& set_host_ipvfuture(core::string_view s) { url_base::set_host_ipvfuture(s); return *this; }
387 /// @copydoc url_base::set_host_name
388 static_url& set_host_name(core::string_view s) { url_base::set_host_name(s); return *this; }
389 /// @copydoc url_base::set_encoded_host_name
390 static_url& set_encoded_host_name(pct_string_view s) { url_base::set_encoded_host_name(s); return *this; }
391 /// @copydoc url_base::set_port_number
392 static_url& set_port_number(std::uint16_t n) { url_base::set_port_number(n); return *this; }
393 /// @copydoc url_base::set_port
394 static_url& set_port(core::string_view s) { url_base::set_port(s); return *this; }
395 /// @copydoc url_base::remove_port
396 static_url& remove_port() noexcept { url_base::remove_port(); return *this; }
397
398 /// @copydoc url_base::set_path_absolute
399 //bool set_path_absolute(bool absolute);
400 /// @copydoc url_base::set_path
401 static_url& set_path(core::string_view s) { url_base::set_path(s); return *this; }
402 /// @copydoc url_base::set_encoded_path
403 static_url& set_encoded_path(pct_string_view s) { url_base::set_encoded_path(s); return *this; }
404
405 /// @copydoc url_base::set_query
406 static_url& set_query(core::string_view s) { url_base::set_query(s); return *this; }
407 /// @copydoc url_base::set_encoded_query
408 static_url& set_encoded_query(pct_string_view s) { url_base::set_encoded_query(s); return *this; }
409 /// @copydoc url_base::remove_query
410 static_url& remove_query() noexcept { url_base::remove_query(); return *this; }
411
412 /// @copydoc url_base::remove_fragment
413 static_url& remove_fragment() noexcept { url_base::remove_fragment(); return *this; }
414 /// @copydoc url_base::set_fragment
415 static_url& set_fragment(core::string_view s) { url_base::set_fragment(s); return *this; }
416 /// @copydoc url_base::set_encoded_fragment
417 static_url& set_encoded_fragment(pct_string_view s) { url_base::set_encoded_fragment(s); return *this; }
418
419 /// @copydoc url_base::remove_origin
420 static_url& remove_origin() { url_base::remove_origin(); return *this; }
421
422 /// @copydoc url_base::normalize
423 static_url& normalize() { url_base::normalize(); return *this; }
424 /// @copydoc url_base::normalize_scheme
425 static_url& normalize_scheme() { url_base::normalize_scheme(); return *this; }
426 /// @copydoc url_base::normalize_authority
427 static_url& normalize_authority() { url_base::normalize_authority(); return *this; }
428 /// @copydoc url_base::normalize_path
429 static_url& normalize_path() { url_base::normalize_path(); return *this; }
430 /// @copydoc url_base::normalize_query
431 static_url& normalize_query() { url_base::normalize_query(); return *this; }
432 /// @copydoc url_base::normalize_fragment
433 static_url& normalize_fragment() { url_base::normalize_fragment(); return *this; }
434
435 //--------------------------------------------
436 };
437
438 } // urls
439 } // boost
440
441 //------------------------------------------------
442
443 // std::hash specialization
444 #ifndef BOOST_URL_DOCS
445 namespace std {
446 template<std::size_t N>
447 struct hash< ::boost::urls::static_url<N> >
448 {
449 hash() = default;
450 hash(hash const&) = default;
451 hash& operator=(hash const&) = default;
452
453 explicit
454 hash(std::size_t salt) noexcept
455 : salt_(salt)
456 {
457 }
458
459 std::size_t
460 operator()(::boost::urls::static_url<N> const& u) const noexcept
461 {
462 return u.digest(salt_);
463 }
464
465 private:
466 std::size_t salt_ = 0;
467 };
468 } // std
469 #endif
470
471 #endif
472