GCC Code Coverage Report


Directory: libs/url/
File: include/boost/url/static_url.hpp
Date: 2025-11-12 22:47:45
Exec Total Coverage
Lines: 22 22 100.0%
Functions: 31 34 91.2%
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/core/detail/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 66 ~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 28 copy(url_view_base const& u)
70 {
71 28 this->url_base::copy(u);
72 25 }
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 + 1
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 62 ~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 30 static_url() noexcept
166 : static_url_base(
167 30 buf_, sizeof(buf_))
168 {
169 30 }
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 36 static_url(
219 core::string_view s)
220 : static_url_base(
221 36 buf_, sizeof(buf_), s)
222 {
223 32 }
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 Throws nothing.
240
241 @param u The url to copy.
242 */
243 1 static_url(
244 static_url const& u) noexcept
245 1 : static_url()
246 {
247 1 copy(u);
248 1 }
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 10 : static_url()
274 {
275
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
10 copy(u);
276 10 }
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 @return A reference to this object.
298 */
299 static_url&
300 operator=(
301 static_url const& u) noexcept
302 {
303 if (this != &u)
304 copy(u);
305 return *this;
306 }
307
308 /** Assignment
309
310 The contents of `u` are copied and
311 the previous contents of `this` are
312 discarded.
313
314 @par Postconditions
315 @code
316 this->buffer() == u.buffer() && this->buffer().data() != u.buffer().data()
317 @endcode
318
319 @par Complexity
320 Linear in `u.size()`.
321
322 @par Exception Safety
323 Strong guarantee.
324 Exception thrown if capacity exceeded.
325
326 @throw system_error
327 Capacity would be exceeded.
328
329 @param u The url to copy.
330 @return A reference to this object.
331 */
332 static_url&
333 5 operator=(
334 url_view_base const& u)
335 {
336 5 copy(u);
337 4 return *this;
338 }
339
340
341 //--------------------------------------------
342 //
343 // fluent api
344 //
345
346 /// @copydoc url_base::set_scheme
347 static_url& set_scheme(core::string_view s) { url_base::set_scheme(s); return *this; }
348 /// @copydoc url_base::set_scheme_id
349 static_url& set_scheme_id(urls::scheme id) { url_base::set_scheme_id(id); return *this; }
350 /// @copydoc url_base::remove_scheme
351 static_url& remove_scheme() { url_base::remove_scheme(); return *this; }
352
353 /// @copydoc url_base::set_encoded_authority
354 static_url& set_encoded_authority(pct_string_view s) { url_base::set_encoded_authority(s); return *this; }
355 /// @copydoc url_base::remove_authority
356 static_url& remove_authority() { url_base::remove_authority(); return *this; }
357
358 /// @copydoc url_base::set_userinfo
359 static_url& set_userinfo(core::string_view s) { url_base::set_userinfo(s); return *this; }
360 /// @copydoc url_base::set_encoded_userinfo
361 static_url& set_encoded_userinfo(pct_string_view s) { url_base::set_encoded_userinfo(s); return *this; }
362 /// @copydoc url_base::remove_userinfo
363 static_url& remove_userinfo() noexcept { url_base::remove_userinfo(); return *this; }
364 /// @copydoc url_base::set_user
365 static_url& set_user(core::string_view s) { url_base::set_user(s); return *this; }
366 /// @copydoc url_base::set_encoded_user
367 static_url& set_encoded_user(pct_string_view s) { url_base::set_encoded_user(s); return *this; }
368 /// @copydoc url_base::set_password
369 static_url& set_password(core::string_view s) { url_base::set_password(s); return *this; }
370 /// @copydoc url_base::set_encoded_password
371 static_url& set_encoded_password(pct_string_view s) { url_base::set_encoded_password(s); return *this; }
372 /// @copydoc url_base::remove_password
373 static_url& remove_password() noexcept { url_base::remove_password(); return *this; }
374
375 /// @copydoc url_base::set_host
376 static_url& set_host(core::string_view s) { url_base::set_host(s); return *this; }
377 /// @copydoc url_base::set_encoded_host
378 static_url& set_encoded_host(pct_string_view s) { url_base::set_encoded_host(s); return *this; }
379 /// @copydoc url_base::set_host_address
380 static_url& set_host_address(core::string_view s) { url_base::set_host_address(s); return *this; }
381 /// @copydoc url_base::set_encoded_host_address
382 static_url& set_encoded_host_address(pct_string_view s) { url_base::set_encoded_host_address(s); return *this; }
383 /// @copydoc url_base::set_host_ipv4
384 static_url& set_host_ipv4(ipv4_address const& addr) { url_base::set_host_ipv4(addr); return *this; }
385 /// @copydoc url_base::set_host_ipv6
386 static_url& set_host_ipv6(ipv6_address const& addr) { url_base::set_host_ipv6(addr); return *this; }
387 /// @copydoc url_base::set_zone_id
388 static_url& set_zone_id(core::string_view s) { url_base::set_zone_id(s); return *this; }
389 /// @copydoc url_base::set_encoded_zone_id
390 static_url& set_encoded_zone_id(pct_string_view const& s) { url_base::set_encoded_zone_id(s); return *this; }
391 /// @copydoc url_base::set_host_ipvfuture
392 static_url& set_host_ipvfuture(core::string_view s) { url_base::set_host_ipvfuture(s); return *this; }
393 /// @copydoc url_base::set_host_name
394 static_url& set_host_name(core::string_view s) { url_base::set_host_name(s); return *this; }
395 /// @copydoc url_base::set_encoded_host_name
396 static_url& set_encoded_host_name(pct_string_view s) { url_base::set_encoded_host_name(s); return *this; }
397 /// @copydoc url_base::set_port_number
398 static_url& set_port_number(std::uint16_t n) { url_base::set_port_number(n); return *this; }
399 /// @copydoc url_base::set_port
400 static_url& set_port(core::string_view s) { url_base::set_port(s); return *this; }
401 /// @copydoc url_base::remove_port
402 static_url& remove_port() noexcept { url_base::remove_port(); return *this; }
403
404 /// @copydoc url_base::set_path_absolute
405 //bool set_path_absolute(bool absolute);
406 /// @copydoc url_base::set_path
407 static_url& set_path(core::string_view s) { url_base::set_path(s); return *this; }
408 /// @copydoc url_base::set_encoded_path
409 static_url& set_encoded_path(pct_string_view s) { url_base::set_encoded_path(s); return *this; }
410
411 /// @copydoc url_base::set_query
412 static_url& set_query(core::string_view s) { url_base::set_query(s); return *this; }
413 /// @copydoc url_base::set_encoded_query
414 static_url& set_encoded_query(pct_string_view s) { url_base::set_encoded_query(s); return *this; }
415 /// @copydoc url_base::set_params
416 static_url& set_params(std::initializer_list<param_view> ps, encoding_opts opts = {}) { url_base::set_params(ps, opts); return *this; }
417 /// @copydoc url_base::remove_query
418 static_url& remove_query() noexcept { url_base::remove_query(); return *this; }
419
420 /// @copydoc url_base::remove_fragment
421 static_url& remove_fragment() noexcept { url_base::remove_fragment(); return *this; }
422 /// @copydoc url_base::set_fragment
423 static_url& set_fragment(core::string_view s) { url_base::set_fragment(s); return *this; }
424 /// @copydoc url_base::set_encoded_fragment
425 static_url& set_encoded_fragment(pct_string_view s) { url_base::set_encoded_fragment(s); return *this; }
426
427 /// @copydoc url_base::remove_origin
428 static_url& remove_origin() { url_base::remove_origin(); return *this; }
429
430 /// @copydoc url_base::normalize
431 static_url& normalize() { url_base::normalize(); return *this; }
432 /// @copydoc url_base::normalize_scheme
433 static_url& normalize_scheme() { url_base::normalize_scheme(); return *this; }
434 /// @copydoc url_base::normalize_authority
435 static_url& normalize_authority() { url_base::normalize_authority(); return *this; }
436 /// @copydoc url_base::normalize_path
437 static_url& normalize_path() { url_base::normalize_path(); return *this; }
438 /// @copydoc url_base::normalize_query
439 static_url& normalize_query() { url_base::normalize_query(); return *this; }
440 /// @copydoc url_base::normalize_fragment
441 static_url& normalize_fragment() { url_base::normalize_fragment(); return *this; }
442
443 //--------------------------------------------
444 };
445
446 } // urls
447 } // boost
448
449 //------------------------------------------------
450
451 // std::hash specialization
452 #ifndef BOOST_URL_DOCS
453 namespace std {
454 template<std::size_t N>
455 struct hash< ::boost::urls::static_url<N> >
456 {
457 hash() = default;
458 hash(hash const&) = default;
459 hash& operator=(hash const&) = default;
460
461 explicit
462 hash(std::size_t salt) noexcept
463 : salt_(salt)
464 {
465 }
466
467 std::size_t
468 operator()(::boost::urls::static_url<N> const& u) const noexcept
469 {
470 return u.digest(salt_);
471 }
472
473 private:
474 std::size_t salt_ = 0;
475 };
476 } // std
477 #endif
478
479 #endif
480