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/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 33 : ~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 31 : ~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 15 : static_url() noexcept
166 : : static_url_base(
167 15 : buf_, sizeof(buf_))
168 : {
169 15 : }
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 18 : static_url(
219 : core::string_view s)
220 : : static_url_base(
221 18 : buf_, sizeof(buf_), s)
222 : {
223 16 : }
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 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 5 : static_url(
272 : url_view_base const& u)
273 5 : : static_url()
274 : {
275 5 : copy(u);
276 5 : }
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
|