include/boost/url/static_url.hpp

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