Line data 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 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
|