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 29 : ~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 27 : ~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 14 : static_url() noexcept 166 : : static_url_base( 167 14 : buf_, sizeof(buf_)) 168 : { 169 14 : } 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 15 : static_url( 219 : core::string_view s) 220 : : static_url_base( 221 15 : buf_, sizeof(buf_), s) 222 : { 223 13 : } 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 0 : static_url( 244 : static_url const& u) noexcept 245 0 : : static_url() 246 : { 247 0 : copy(u); 248 0 : } 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 6 : : static_url() 274 : { 275 5 : copy(u); 276 4 : } 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