// // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/url // #ifndef BOOST_URL_URL_VIEW_BASE_HPP #define BOOST_URL_URL_VIEW_BASE_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace urls { #ifndef BOOST_URL_DOCS namespace detail { struct pattern; } #endif /** Common functionality for containers This base class is used by the library to provide common member functions for containers. This cannot be instantiated directly; Instead, use one of the containers or functions: @par Containers @li @ref url @li @ref url_view @li @ref static_url @par Functions @li @ref parse_absolute_uri @li @ref parse_origin_form @li @ref parse_relative_ref @li @ref parse_uri @li @ref parse_uri_reference */ class BOOST_URL_DECL url_view_base : private detail::parts_base { detail::url_impl impl_; detail::url_impl const* pi_; friend class url; friend class url_base; friend class url_view; friend class static_url_base; friend class params_base; friend class params_encoded_base; friend class params_encoded_ref; friend class params_encoded_view; friend class params_ref; friend class params_view; friend class segments_base; friend class segments_encoded_base; friend class segments_encoded_ref; friend class segments_encoded_view; friend class segments_ref; friend class segments_view; friend struct detail::pattern; struct shared_impl; url_view_base() noexcept; explicit url_view_base( detail::url_impl const&) noexcept; ~url_view_base() = default; url_view_base( url_view_base const& o) noexcept : impl_(o.impl_) , pi_(o.pi_) { if (pi_ == &o.impl_) pi_ = &impl_; } url_view_base& operator=( url_view_base const&) = delete; protected: /** Calculate a hash of the url This function calculates a hash of the url as if it were always normalized. @par Complexity Linear in `this->size()`. @par Exception Safety Throws nothing. @param salt An initial value to add to the hash @return A hash value suitable for use in hash-based containers. */ std::size_t digest(std::size_t salt = 0) const noexcept; public: //-------------------------------------------- // // Observers // //-------------------------------------------- /** Return the maximum number of characters possible This represents the largest number of characters that are theoretically possible to represent in a url, not including any null terminator. In practice the actual possible size may be lower than this number. @par Complexity Constant. @par Exception Safety Throws nothing. @return The maximum number of characters. */ static constexpr std::size_t max_size() noexcept { return BOOST_URL_MAX_SIZE; } /** Return the number of characters in the url This function returns the number of characters in the url's encoded string, not including any null terminator, if present. @par Example @code assert( url_view( "file:///Program%20Files" ).size() == 23 ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @return The number of characters in the url. */ std::size_t size() const noexcept { return pi_->offset(id_end); } /** Return true if the url is empty The empty string matches the relative-ref grammar. @par Example @code assert( url_view( "" ).empty() ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code relative-ref = relative-part [ "?" query ] [ "#" fragment ] relative-part = "//" authority path-abempty / path-absolute / path-noscheme / path-empty @endcode @par Specification @li 4.2. Relative Reference (rfc3986) @return `true` if the url is empty. */ bool empty() const noexcept { return pi_->offset(id_end) == 0; } /** Return a pointer to the url's character buffer This function returns a pointer to the first character of the url, which is not guaranteed to be null-terminated. @par Complexity Constant. @par Exception Safety Throws nothing. @return A pointer to the first character. */ char const* data() const noexcept { return pi_->cs_; } /** Return the url string This function returns the entire url, which may contain percent escapes. @par Example @code assert( url_view( "http://www.example.com" ).buffer() == "http://www.example.com" ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @return The url as a string. */ core::string_view buffer() const noexcept { return core::string_view( data(), size()); } /** Return the URL as a core::string_view @par Complexity Constant. @par Exception Safety Throws nothing. @return A string view of the URL. */ operator core::string_view() const noexcept { return buffer(); } /** Return a shared, persistent copy of the url This function returns a read-only copy of the url, with shared lifetime. The returned value owns (persists) the underlying string. The algorithm used to create the value minimizes the number of individual memory allocations, making it more efficient than when using direct standard library functions. @par Example @code std::shared_ptr< url_view const > sp; { std::string s( "http://example.com" ); url_view u( s ); // u references characters in s assert( u.data() == s.data() ); // same buffer sp = u.persist(); assert( sp->data() != s.data() ); // different buffer assert( sp->buffer() == s); // same contents // s is destroyed and thus u // becomes invalid, but sp remains valid. } @endcode @par Complexity Linear in `this->size()`. @par Exception Safety Calls to allocate may throw. @return A shared pointer to a read-only url_view. */ std::shared_ptr< url_view const> persist() const; //-------------------------------------------- // // Scheme // //-------------------------------------------- /** Return true a scheme is present This function returns true if this contains a scheme. @par Example @code assert( url_view( "http://www.example.com" ).has_scheme() ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] absolute-URI = scheme ":" hier-part [ "?" query ] scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) @endcode @par Specification @li 3.1. Scheme (rfc3986) @see @ref scheme, @ref scheme_id. @return `true` if the url contains a scheme. */ bool has_scheme() const noexcept; /** Return the scheme This function returns the scheme if it exists, without a trailing colon (':'). Otherwise it returns an empty string. Note that schemes are case-insensitive, and the canonical form is lowercased. @par Example @code assert( url_view( "http://www.example.com" ).scheme() == "http" ); @endcode @par Exception Safety Throws nothing. @par BNF @code scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] absolute-URI = scheme ":" hier-part [ "?" query ] @endcode @par Specification @li 3.1. Scheme (rfc3986) @see @ref has_scheme, @ref scheme_id. @return The scheme as a string. */ core::string_view scheme() const noexcept; /** Return the scheme This function returns a value which depends on the scheme in the url: @li If the scheme is a well-known scheme, corresponding value from the enumeration @ref urls::scheme is returned. @li If a scheme is present but is not a well-known scheme, the value returned is @ref urls::scheme::unknown. @li Otherwise, if the scheme is absent the value returned is @ref urls::scheme::none. @par Example @code assert( url_view( "wss://www.example.com/crypto.cgi" ).scheme_id() == scheme::wss ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] absolute-URI = scheme ":" hier-part [ "?" query ] scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) @endcode @par Specification @li 3.1. Scheme (rfc3986) @see @ref has_scheme, @ref scheme. @return The scheme as an enumeration value. */ urls::scheme scheme_id() const noexcept; //-------------------------------------------- // // Authority // //-------------------------------------------- /** Return true if an authority is present This function returns true if the url contains an authority. The presence of an authority is denoted by a double slash ("//") at the beginning or after the scheme. @par Example @code assert( url_view( "http://www.example.com/index.htm" ).has_authority() ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code authority = [ userinfo "@" ] host [ ":" port ] URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] absolute-URI = scheme ":" hier-part [ "?" query ] URI-reference = URI / relative-ref relative-ref = relative-part [ "?" query ] [ "#" fragment ] hier-part = "//" authority path-abempty ; (more...) relative-part = "//" authority path-abempty ; (more...) @endcode @par Specification @li 3.2. Authority (rfc3986) @see @ref authority, @ref encoded_authority. @return `true` if the url contains an authority. */ bool has_authority() const noexcept { return pi_->len(id_user) > 0; } /** Return the authority This function returns the authority as an @ref authority_view. @par Example @code authority_view a = url_view( "https://www.example.com:8080/index.htm" ).authority(); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code authority = [ userinfo "@" ] host [ ":" port ] @endcode @par Specification @li 3.2. Authority (rfc3986) @see @ref encoded_authority, @ref has_authority. @return An authority_view representing the authority. */ authority_view authority() const noexcept; /** Return the authority. If present, this function returns a string representing the authority (which may be empty). Otherwise it returns an empty string. The returned string may contain percent escapes. @par Example @code assert( url_view( "file://Network%20Drive/My%2DFiles" ).encoded_authority() == "Network%20Drive" ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code authority = [ userinfo "@" ] host [ ":" port ] @endcode @par Specification @li 3.2. Authority (rfc3986) @see @ref authority, @ref has_authority. @return The authority as a string. */ pct_string_view encoded_authority() const noexcept; //-------------------------------------------- // // Userinfo // //-------------------------------------------- /** Return true if a userinfo is present This function returns true if this contains a userinfo. @par Example @code assert( url_view( "http://jane%2Ddoe:pass@example.com" ).has_userinfo() ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code userinfo = user [ ":" [ password ] ] authority = [ userinfo "@" ] host [ ":" port ] @endcode @par Specification @li 3.2.1. User Information (rfc3986) @see @ref has_password, @ref encoded_password, @ref encoded_user, @ref encoded_userinfo, @ref password, @ref user, @ref userinfo. @return `true` if the userinfo is present. */ bool has_userinfo() const noexcept; /** Return true if a password is present This function returns true if the userinfo is present and contains a password. @par Example @code assert( url_view( "http://jane%2Ddoe:pass@example.com" ).has_password() ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code userinfo = user [ ":" [ password ] ] user = *( unreserved / pct-encoded / sub-delims ) password = *( unreserved / pct-encoded / sub-delims / ":" ) @endcode @par Specification @li 3.2.1. User Information (rfc3986) @see @ref has_userinfo, @ref encoded_password, @ref encoded_user, @ref encoded_userinfo, @ref password, @ref user, @ref userinfo. @return `true` if the userinfo contains a password. */ bool has_password() const noexcept; /** Return the userinfo If present, this function returns a string representing the userinfo (which may be empty). Otherwise it returns an empty string. Any percent-escapes in the string are decoded first. @note This function uses the string token return type customization. Depending on the token passed, the return type and behavior of the function can be different. See @ref string_token::return_string for more information. @par Example @code assert( url_view( "http://jane%2Ddoe:pass@example.com" ).userinfo() == "jane-doe:pass" ); @endcode @par Complexity Linear in `this->userinfo().size()`. @par Exception Safety Calls to allocate may throw. @return When called with no arguments, a value of type `std::string` is returned. Otherwise, the return type and meaning depends on the string token passed to the function. @par BNF @code userinfo = user [ ":" [ password ] ] authority = [ userinfo "@" ] host [ ":" port ] @endcode @par Specification @li 3.2.1. User Information (rfc3986) @see @ref has_password, @ref has_userinfo, @ref encoded_password, @ref encoded_user, @ref encoded_userinfo, @ref password, @ref user. @param token The string token to use. @return The userinfo as a string. */ template BOOST_URL_STRTOK_RETURN userinfo( StringToken&& token = {}) const { encoding_opts opt; opt.space_as_plus = false; return encoded_userinfo().decode( opt, std::forward(token)); } /** Return the userinfo If present, this function returns a string representing the userinfo (which may be empty). Otherwise it returns an empty string. The returned string may contain percent escapes. @par Example @code assert( url_view( "http://jane%2Ddoe:pass@example.com" ).encoded_userinfo() == "jane%2Ddoe:pass" ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing @par BNF @code userinfo = user [ ":" [ password ] ] authority = [ userinfo "@" ] host [ ":" port ] @endcode @par Specification @li 3.2.1. User Information (rfc3986) @see @ref has_password, @ref has_userinfo, @ref encoded_password, @ref encoded_user, @ref password, @ref user, @ref userinfo. @return The userinfo as a string. */ pct_string_view encoded_userinfo() const noexcept; //-------------------------------------------- /** Return the user If present, this function returns a string representing the user (which may be empty). Otherwise it returns an empty string. Any percent-escapes in the string are decoded first. @par Example @code assert( url_view( "http://jane%2Ddoe:pass@example.com" ).user() == "jane-doe" ); @endcode @par Complexity Linear in `this->user().size()`. @par Exception Safety Calls to allocate may throw. @par BNF @code userinfo = user [ ":" [ password ] ] user = *( unreserved / pct-encoded / sub-delims ) password = *( unreserved / pct-encoded / sub-delims / ":" ) @endcode @par Specification @li 3.2.1. User Information (rfc3986) @see @ref has_password, @ref has_userinfo, @ref encoded_password, @ref encoded_user, @ref encoded_userinfo, @ref password, @ref userinfo. @param token The string token to use. @return The user as a string. */ template BOOST_URL_STRTOK_RETURN user( StringToken&& token = {}) const { encoding_opts opt; opt.space_as_plus = false; return encoded_user().decode( opt, std::forward(token)); } /** Return the user If present, this function returns a string representing the user (which may be empty). Otherwise it returns an empty string. The returned string may contain percent escapes. @par Example @code assert( url_view( "http://jane%2Ddoe:pass@example.com" ).encoded_user() == "jane%2Ddoe" ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code userinfo = user [ ":" [ password ] ] user = *( unreserved / pct-encoded / sub-delims ) password = *( unreserved / pct-encoded / sub-delims / ":" ) @endcode @par Specification @li 3.2.1. User Information (rfc3986) @see @ref has_password, @ref has_userinfo, @ref encoded_password, @ref encoded_userinfo, @ref password, @ref user, @ref userinfo. @return The user as a string. */ pct_string_view encoded_user() const noexcept; /** Return the password If present, this function returns a string representing the password (which may be an empty string). Otherwise it returns an empty string. Any percent-escapes in the string are decoded first. @par Example @code assert( url_view( "http://jane%2Ddoe:pass@example.com" ).password() == "pass" ); @endcode @par Complexity Linear in `this->password().size()`. @par Exception Safety Calls to allocate may throw. @par BNF @code userinfo = user [ ":" [ password ] ] user = *( unreserved / pct-encoded / sub-delims ) password = *( unreserved / pct-encoded / sub-delims / ":" ) @endcode @par Specification @li 3.2.1. User Information (rfc3986) @see @ref has_password, @ref has_userinfo, @ref encoded_password, @ref encoded_user, @ref encoded_userinfo, @ref user, @ref userinfo. @param token The string token to use. @return The password as a string. */ template BOOST_URL_STRTOK_RETURN password( StringToken&& token = {}) const { encoding_opts opt; opt.space_as_plus = false; return encoded_password().decode( opt, std::forward(token)); } /** Return the password This function returns the password portion of the userinfo as a percent-encoded string. @par Example @code assert( url_view( "http://jane%2Ddoe:pass@example.com" ).encoded_password() == "pass" ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code userinfo = user [ ":" [ password ] ] user = *( unreserved / pct-encoded / sub-delims ) password = *( unreserved / pct-encoded / sub-delims / ":" ) @endcode @par Specification @li 3.2.1. User Information (rfc3986) @see @ref has_password, @ref has_userinfo, @ref encoded_user, @ref encoded_userinfo, @ref password, @ref user, @ref userinfo. @return The password as a string. */ pct_string_view encoded_password() const noexcept; //-------------------------------------------- // // Host // //-------------------------------------------- /** Return the host type This function returns one of the following constants representing the type of host present. @li @ref host_type::ipv4 @li @ref host_type::ipv6 @li @ref host_type::ipvfuture @li @ref host_type::name @li @ref host_type::none When @ref has_authority is false, the host type is @ref host_type::none. @par Example @code assert( url_view( "https://192.168.0.1/local.htm" ).host_type() == host_type::ipv4 ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par Specification @li 3.2.2. Host (rfc3986) @return The type of host present. */ urls::host_type host_type() const noexcept { return pi_->host_type_; } /** Return the host This function returns the host portion of the authority as a string, or the empty string if there is no authority. Any percent-escapes in the string are decoded first. @par Example @code assert( url_view( "https://www%2droot.example.com/" ).host() == "www-root.example.com" ); @endcode @par Complexity Linear in `this->host().size()`. @par Exception Safety Calls to allocate may throw. @par BNF @code host = IP-literal / IPv4address / reg-name IP-literal = "[" ( IPv6address / IPvFuture ) "]" reg-name = *( unreserved / pct-encoded / "-" / ".") @endcode @par Specification @li 3.2.2. Host (rfc3986) @param token A string token customization @return The host address as a string. */ template BOOST_URL_STRTOK_RETURN host( StringToken&& token = {}) const { encoding_opts opt; opt.space_as_plus = false; return encoded_host().decode( opt, std::forward(token)); } /** Return the host This function returns the host portion of the authority as a string, or the empty string if there is no authority. The returned string may contain percent escapes. @par Example @code assert( url_view( "https://www%2droot.example.com/" ).encoded_host() == "www%2droot.example.com" ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code host = IP-literal / IPv4address / reg-name IP-literal = "[" ( IPv6address / IPvFuture ) "]" reg-name = *( unreserved / pct-encoded / "-" / ".") @endcode @par Specification @li 3.2.2. Host (rfc3986) @return The host address as a string. */ pct_string_view encoded_host() const noexcept; /** Return the host The value returned by this function depends on the type of host returned from the function @ref host_type. @li If the type is @ref host_type::ipv4, then the IPv4 address string is returned. @li If the type is @ref host_type::ipv6, then the IPv6 address string is returned, without any enclosing brackets. @li If the type is @ref host_type::ipvfuture, then the IPvFuture address string is returned, without any enclosing brackets. @li If the type is @ref host_type::name, then the host name string is returned. Any percent-escapes in the string are decoded first. @li If the type is @ref host_type::none, then an empty string is returned. @par Example @code assert( url_view( "https://[1::6:c0a8:1]/" ).host_address() == "1::6:c0a8:1" ); @endcode @par Complexity Linear in `this->host_address().size()`. @par Exception Safety Calls to allocate may throw. @par BNF @code host = IP-literal / IPv4address / reg-name IP-literal = "[" ( IPv6address / IPvFuture ) "]" reg-name = *( unreserved / pct-encoded / "-" / ".") @endcode @par Specification @li 3.2.2. Host (rfc3986) @param token A string token customization @return The host address as a string. */ template BOOST_URL_STRTOK_RETURN host_address( StringToken&& token = {}) const { encoding_opts opt; opt.space_as_plus = false; return encoded_host_address().decode( opt, std::forward(token)); } /** Return the host The value returned by this function depends on the type of host returned from the function @ref host_type. @li If the type is @ref host_type::ipv4, then the IPv4 address string is returned. @li If the type is @ref host_type::ipv6, then the IPv6 address string is returned, without any enclosing brackets. @li If the type is @ref host_type::ipvfuture, then the IPvFuture address string is returned, without any enclosing brackets. @li If the type is @ref host_type::name, then the host name string is returned. Any percent-escapes in the string are decoded first. @li If the type is @ref host_type::none, then an empty string is returned. The returned string may contain percent escapes. @par Example @code assert( url_view( "https://www%2droot.example.com/" ).encoded_host_address() == "www%2droot.example.com" ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code host = IP-literal / IPv4address / reg-name IP-literal = "[" ( IPv6address / IPvFuture ) "]" reg-name = *( unreserved / pct-encoded / "-" / ".") @endcode @par Specification @li 3.2.2. Host (rfc3986) @return The host address as a string. */ pct_string_view encoded_host_address() const noexcept; /** Return the host IPv4 address If the host type is @ref host_type::ipv4, this function returns the address as a value of type @ref ipv4_address. Otherwise, if the host type is not an IPv4 address, it returns a default-constructed value which is equal to the unspecified address "0.0.0.0". @par Example @code assert( url_view( "http://127.0.0.1/index.htm?user=win95" ).host_ipv4_address() == ipv4_address( "127.0.0.1" ) ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet dec-octet = DIGIT ; 0-9 / %x31-39 DIGIT ; 10-99 / "1" 2DIGIT ; 100-199 / "2" %x30-34 DIGIT ; 200-249 / "25" %x30-35 ; 250-255 @endcode @par Specification @li 3.2.2. Host (rfc3986) @return The IPv4 address as a value of type @ref ipv4_address. */ ipv4_address host_ipv4_address() const noexcept; /** Return the host IPv6 address If the host type is @ref host_type::ipv6, this function returns the address as a value of type @ref ipv6_address. Otherwise, if the host type is not an IPv6 address, it returns a default-constructed value which is equal to the unspecified address "0:0:0:0:0:0:0:0". @par Example @code assert( url_view( "ftp://[::1]/" ).host_ipv6_address() == ipv6_address( "::1" ) ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code IPv6address = 6( h16 ":" ) ls32 / "::" 5( h16 ":" ) ls32 / [ h16 ] "::" 4( h16 ":" ) ls32 / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32 / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32 / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32 / [ *4( h16 ":" ) h16 ] "::" ls32 / [ *5( h16 ":" ) h16 ] "::" h16 / [ *6( h16 ":" ) h16 ] "::" ls32 = ( h16 ":" h16 ) / IPv4address ; least-significant 32 bits of address h16 = 1*4HEXDIG ; 16 bits of address represented in hexadecimal @endcode @par Specification @li 3.2.2. Host (rfc3986) @return The IPv6 address as a value of type @ref ipv6_address. */ ipv6_address host_ipv6_address() const noexcept; /** Return the host IPvFuture address If the host type is @ref host_type::ipvfuture, this function returns the address as a string. Otherwise, if the host type is not an IPvFuture address, it returns an empty string. @par Example @code assert( url_view( "http://[v1fe.d:9]/index.htm" ).host_ipvfuture() == "v1fe.d:9" ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) @endcode @par Specification @li 3.2.2. Host (rfc3986) @return The IPvFuture address as a string. */ core::string_view host_ipvfuture() const noexcept; /** Return the host name If the host type is @ref host_type::name, this function returns the name as a string. Otherwise an empty string is returned. Any percent-escapes in the string are decoded first. @par Example @code assert( url_view( "https://www%2droot.example.com/" ).host_name() == "www-root.example.com" ); @endcode @par Complexity Linear in `this->host_name().size()`. @par Exception Safety Calls to allocate may throw. @par BNF @code host = IP-literal / IPv4address / reg-name IP-literal = "[" ( IPv6address / IPvFuture ) "]" reg-name = *( unreserved / pct-encoded / "-" / ".") @endcode @par Specification @li 3.2.2. Host (rfc3986) @param token A string token customization. @return The host name as a string. */ template BOOST_URL_STRTOK_RETURN host_name( StringToken&& token = {}) const { encoding_opts opt; opt.space_as_plus = false; return encoded_host_name().decode( opt, std::forward(token)); } /** Return the host name If the host type is @ref host_type::name, this function returns the name as a string. Otherwise, if the host type is not an name, it returns an empty string. The returned string may contain percent escapes. @par Example @code assert( url_view( "https://www%2droot.example.com/" ).encoded_host_name() == "www%2droot.example.com" ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code host = IP-literal / IPv4address / reg-name IP-literal = "[" ( IPv6address / IPvFuture ) "]" reg-name = *( unreserved / pct-encoded / "-" / ".") @endcode @par Specification @li 3.2.2. Host (rfc3986) @return The host name as a percent-encoded string. */ pct_string_view encoded_host_name() const noexcept; /** Return the IPv6 Zone ID If the host type is @ref host_type::ipv6, this function returns the Zone ID as a string. Otherwise an empty string is returned. Any percent-escapes in the string are decoded first. @par Example @code assert( url_view( "http://[fe80::1%25eth0]/" ).zone_id() == "eth0" ); @endcode @par Complexity Linear in `this->encoded_zone_id().size()`. @par Exception Safety Calls to allocate may throw. @par BNF @code host = IP-literal / IPv4address / reg-name IP-literal = "[" ( IPv6address / IPv6addrz / IPvFuture ) "]" ZoneID = 1*( unreserved / pct-encoded ) IPv6addrz = IPv6address "%25" ZoneID @endcode @par Specification @li Representing IPv6 Zone Identifiers in Address Literals and Uniform Resource Identifiers @param token A string token customization. @return The Zone ID as a string. */ template BOOST_URL_STRTOK_RETURN zone_id( StringToken&& token = {}) const { encoding_opts opt; opt.space_as_plus = false; return encoded_zone_id().decode( opt, std::forward(token)); } /** Return the IPv6 Zone ID If the host type is @ref host_type::ipv6, this function returns the Zone ID as a string. Otherwise an empty string is returned. The returned string may contain percent escapes. @par Example @code assert( url_view( "http://[fe80::1%25eth0]/" ).encoded_zone_id() == "eth0" ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code host = IP-literal / IPv4address / reg-name IP-literal = "[" ( IPv6address / IPv6addrz / IPvFuture ) "]" ZoneID = 1*( unreserved / pct-encoded ) IPv6addrz = IPv6address "%25" ZoneID @endcode @par Specification @li Representing IPv6 Zone Identifiers in Address Literals and Uniform Resource Identifiers @return The Zone ID as a percent-encoded string. */ pct_string_view encoded_zone_id() const noexcept; //-------------------------------------------- // // Port // //-------------------------------------------- /** Return true if a port is present This function returns true if an authority is present and contains a port. @par Example @code assert( url_view( "wss://www.example.com:443" ).has_port() ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code authority = [ userinfo "@" ] host [ ":" port ] port = *DIGIT @endcode @par Specification @li 3.2.3. Port (rfc3986) @see @ref encoded_host_and_port, @ref port, @ref port_number. @return `true` if a port is present, `false` otherwise. */ bool has_port() const noexcept; /** Return the port If present, this function returns a string representing the port (which may be empty). Otherwise it returns an empty string. @par Example @code assert( url_view( "http://localhost.com:8080" ).port() == "8080" ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code port = *DIGIT @endcode @par Specification @li 3.2.3. Port (rfc3986) @see @ref encoded_host_and_port, @ref has_port, @ref port_number. @return The port as a string. */ core::string_view port() const noexcept; /** Return the port If a port is present and the numerical value is representable, it is returned as an unsigned integer. Otherwise, the number zero is returned. @par Example @code assert( url_view( "http://localhost.com:8080" ).port_number() == 8080 ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code port = *DIGIT @endcode @par Specification @li 3.2.3. Port (rfc3986) @see @ref encoded_host_and_port, @ref has_port, @ref port. @return The port number as an unsigned integer. */ std::uint16_t port_number() const noexcept; //-------------------------------------------- // // Path // //-------------------------------------------- /** Return true if the path is absolute This function returns true if the path begins with a forward slash ('/'). @par Example @code assert( url_view( "/path/to/file.txt" ).is_path_absolute() ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code path = path-abempty ; begins with "/" or is empty / path-absolute ; begins with "/" but not "//" / path-noscheme ; begins with a non-colon segment / path-rootless ; begins with a segment / path-empty ; zero characters path-abempty = *( "/" segment ) path-absolute = "/" [ segment-nz *( "/" segment ) ] path-noscheme = segment-nz-nc *( "/" segment ) path-rootless = segment-nz *( "/" segment ) path-empty = 0 @endcode @par Specification @li 3.3. Path (rfc3986) @see @ref encoded_path, @ref encoded_segments. @ref path, @ref segments. @return `true` if the path is absolute, `false` otherwise. */ bool is_path_absolute() const noexcept { return pi_->len(id_path) > 0 && pi_->cs_[pi_->offset(id_path)] == '/'; } /** Return the path This function returns the path as a string. The path may be empty. Any percent-escapes in the string are decoded first. @par Example @code assert( url_view( "file:///Program%20Files/Games/config.ini" ).path() == "/Program Files/Games/config.ini" ); @endcode @par Complexity Linear in `this->path().size()`. @par Exception Safety Calls to allocate may throw. @par BNF @code path = path-abempty ; begins with "/" or is empty / path-absolute ; begins with "/" but not "//" / path-noscheme ; begins with a non-colon segment / path-rootless ; begins with a segment / path-empty ; zero characters path-abempty = *( "/" segment ) path-absolute = "/" [ segment-nz *( "/" segment ) ] path-noscheme = segment-nz-nc *( "/" segment ) path-rootless = segment-nz *( "/" segment ) path-empty = 0 @endcode @par Specification @li 3.3. Path (rfc3986) @see @ref is_path_absolute, @ref encoded_path, @ref encoded_segments. @ref segments. @param token A string token to use for the result. @return The path as a string. */ template BOOST_URL_STRTOK_RETURN path( StringToken&& token = {}) const { encoding_opts opt; opt.space_as_plus = false; return encoded_path().decode( opt, std::forward(token)); } /** Return the path This function returns the path as a string. The path may be empty. Any percent-escapes in the string are decoded first. @par Example @code assert( url_view( "file:///Program%20Files/Games/config.ini" ).encoded_path() == "/Program%20Files/Games/config.ini" ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code path = path-abempty ; begins with "/" or is empty / path-absolute ; begins with "/" but not "//" / path-noscheme ; begins with a non-colon segment / path-rootless ; begins with a segment / path-empty ; zero characters path-abempty = *( "/" segment ) path-absolute = "/" [ segment-nz *( "/" segment ) ] path-noscheme = segment-nz-nc *( "/" segment ) path-rootless = segment-nz *( "/" segment ) path-empty = 0 @endcode @par Specification @li 3.3. Path (rfc3986) @see @ref is_path_absolute, @ref encoded_segments. @ref path, @ref segments. @return The path as a string. */ pct_string_view encoded_path() const noexcept; /** Return the path as a container of segments This function returns a bidirectional view of strings over the path. The returned view references the same underlying character buffer; ownership is not transferred. Any percent-escapes in strings returned when iterating the view are decoded first. @par Example @code segments_view sv = url_view( "/path/to/file.txt" ).segments(); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code path = [ "/" ] segment *( "/" segment ) @endcode @par Specification @li 3.3. Path (rfc3986) @see @ref is_path_absolute, @ref encoded_path, @ref encoded_segments. @ref path, @ref segments_view. @return A bidirectional view of segments. */ segments_view segments() const noexcept; /** Return the path as a container of segments This function returns a bidirectional view of strings over the path. The returned view references the same underlying character buffer; ownership is not transferred. Strings returned when iterating the range may contain percent escapes. @par Example @code segments_encoded_view sv = url_view( "/path/to/file.txt" ).encoded_segments(); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code path = path-abempty ; begins with "/" or is empty / path-absolute ; begins with "/" but not "//" / path-noscheme ; begins with a non-colon segment / path-rootless ; begins with a segment / path-empty ; zero characters path-abempty = *( "/" segment ) path-absolute = "/" [ segment-nz *( "/" segment ) ] path-noscheme = segment-nz-nc *( "/" segment ) path-rootless = segment-nz *( "/" segment ) path-empty = 0 @endcode @par Specification @li 3.3. Path (rfc3986) @see @ref is_path_absolute, @ref encoded_path, @ref path, @ref segments, @ref segments_encoded_view. @return A bidirectional view of encoded segments. */ segments_encoded_view encoded_segments() const noexcept; //-------------------------------------------- // // Query // //-------------------------------------------- /** Return true if a query is present This function returns true if this contains a query. An empty query is distinct from having no query. @par Example @code assert( url_view( "/sql?id=42&col=name&page-size=20" ).has_query() ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code query = *( pchar / "/" / "?" ) query-param = key [ "=" value ] query-params = [ query-param ] *( "&" query-param ) @endcode @par Specification @li 3.4. Query (rfc3986) @li Query string (Wikipedia) @see @ref encoded_params, @ref encoded_query, @ref params, @ref query. @return `true` if a query is present. */ bool has_query() const noexcept; /** Return the query If this contains a query, it is returned as a string (which may be empty). Otherwise, an empty string is returned. Any percent-escapes in the string are decoded first.
When plus signs appear in the query portion of the url, they are converted to spaces automatically upon decoding. This behavior can be changed by setting decode options. @par Example @code assert( url_view( "/sql?id=42&name=jane%2Ddoe&page+size=20" ).query() == "id=42&name=jane-doe&page size=20" ); @endcode @par Complexity Linear in `this->query().size()`. @par Exception Safety Calls to allocate may throw. @par BNF @code query = *( pchar / "/" / "?" ) query-param = key [ "=" value ] query-params = [ query-param ] *( "&" query-param ) @endcode @par Specification @li 3.4. Query (rfc3986) @li Query string (Wikipedia) @see @ref encoded_params, @ref encoded_query, @ref has_query, @ref params. @param token A token to use for the returned string. @return The query as a string. */ template BOOST_URL_STRTOK_RETURN query( StringToken&& token = {}) const { // When interacting with the query as // an intact string, we do not treat // the plus sign as an encoded space. encoding_opts opt; opt.space_as_plus = false; return encoded_query().decode( opt, std::forward(token)); } /** Return the query If this contains a query, it is returned as a string (which may be empty). Otherwise, an empty string is returned. The returned string may contain percent escapes. @par Example @code assert( url_view( "/sql?id=42&name=jane%2Ddoe&page+size=20" ).encoded_query() == "id=42&name=jane%2Ddoe&page+size=20" ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code query = *( pchar / "/" / "?" ) query-param = key [ "=" value ] query-params = [ query-param ] *( "&" query-param ) @endcode @par Specification @li 3.4. Query (rfc3986) @li Query string (Wikipedia) @see @ref encoded_params, @ref has_query, @ref params, @ref query. @return The query as a string. */ pct_string_view encoded_query() const noexcept; /** Return the query as a container of parameters This function returns a bidirectional view of key/value pairs over the query. The returned view references the same underlying character buffer; ownership is not transferred. Any percent-escapes in strings returned when iterating the view are decoded first. @par Example @code params_view pv = url_view( "/sql?id=42&name=jane%2Ddoe&page+size=20" ).params(); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code query = *( pchar / "/" / "?" ) query-param = key [ "=" value ] query-params = [ query-param ] *( "&" query-param ) @endcode @par Specification @li 3.4. Query (rfc3986) @li Query string (Wikipedia) @see @ref encoded_params, @ref encoded_query, @ref has_query, @ref query. @return A bidirectional view of key/value pairs. */ params_view params() const noexcept; params_view params(encoding_opts opt) const noexcept; /** Return the query as a container of parameters This function returns a bidirectional view of key/value pairs over the query. The returned view references the same underlying character buffer; ownership is not transferred. Strings returned when iterating the range may contain percent escapes. @par Example @code params_encoded_view pv = url_view( "/sql?id=42&name=jane%2Ddoe&page+size=20" ).encoded_params(); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code query = *( pchar / "/" / "?" ) query-param = key [ "=" value ] query-params = [ query-param ] *( "&" query-param ) @endcode @par Specification @li 3.4. Query (rfc3986) @li Query string (Wikipedia) @see @ref encoded_query, @ref has_query, @ref params, @ref query. @return A bidirectional view of key/value pairs. */ params_encoded_view encoded_params() const noexcept; //-------------------------------------------- // // Fragment // //-------------------------------------------- /** Return true if a fragment is present This function returns true if the url contains a fragment. An empty fragment is distinct from no fragment. @par Example @code assert( url_view( "http://www.example.com/index.htm#anchor" ).has_fragment() ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] relative-ref = relative-part [ "?" query ] [ "#" fragment ] @endcode @par Specification @li 3.5. Fragment (rfc3986) @see @ref encoded_fragment, @ref fragment. @return `true` if the url contains a fragment. */ bool has_fragment() const noexcept; /** Return the fragment This function calculates the fragment of the url, with percent escapes decoded and without the leading pound sign ('#') whose presence indicates that the url contains a fragment.
This function accepts an optional StringToken parameter which controls the return type and behavior of the function: @li When called with no arguments, the return type of the function is `std::string`. Otherwise @li When called with a string token, the behavior and return type of the function depends on the type of string token being passed. @par Example @code assert( url_view( "http://www.example.com/index.htm#a%2D1" ).fragment() == "a-1" ); @endcode @par Complexity Linear in `this->fragment().size()`. @par Exception Safety Calls to allocate may throw. String tokens may throw exceptions. @param token An optional string token to use. If this parameter is omitted, the function returns a new `std::string`. @return The fragment portion of the url. @par BNF @code fragment = *( pchar / "/" / "?" ) fragment-part = [ "#" fragment ] @endcode @par Specification @li 3.5. Fragment (rfc3986) @see @ref encoded_fragment, @ref has_fragment. */ template BOOST_URL_STRTOK_RETURN fragment( StringToken&& token = {}) const { encoding_opts opt; opt.space_as_plus = false; return encoded_fragment().decode( opt, std::forward(token)); } /** Return the fragment This function returns the fragment as a string with percent-escapes. Ownership is not transferred; the string returned references the underlying character buffer, which must remain valid or else undefined behavior occurs. @par Example @code assert( url_view( "http://www.example.com/index.htm#a%2D1" ).encoded_fragment() == "a%2D1" ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code fragment = *( pchar / "/" / "?" ) pchar = unreserved / pct-encoded / sub-delims / ":" / "@" @endcode @par Specification @li 3.5. Fragment (rfc3986) @see @ref fragment, @ref has_fragment. @return The fragment portion of the url. */ pct_string_view encoded_fragment() const noexcept; //-------------------------------------------- // // Compound Fields // //-------------------------------------------- /** Return the host and port If an authority is present, this function returns the host and optional port as a string, which may be empty. Otherwise it returns an empty string. The returned string may contain percent escapes. @par Example @code assert( url_view( "http://www.example.com:8080/index.htm" ).encoded_host_and_port() == "www.example.com:8080" ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par BNF @code authority = [ userinfo "@" ] host [ ":" port ] @endcode @par Specification @li 3.2.2. Host (rfc3986) @li 3.2.3. Port (rfc3986) @see @ref has_port, @ref port, @ref port_number. @return The host and port portion of the url. */ pct_string_view encoded_host_and_port() const noexcept; /** Return the origin If an authority is present, this function returns the scheme and authority portion of the url. Otherwise, an empty string is returned. The returned string may contain percent escapes. @par Example @code assert( url_view( "http://www.example.com:8080/index.htm?text=none#h1" ).encoded_origin() == "http://www.example.com:8080" ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @see @ref encoded_resource, @ref encoded_target. @return The origin portion of the url. */ pct_string_view encoded_origin() const noexcept; /** Return the resource This function returns the resource, which is the portion of the url that includes only the path, query, and fragment. The returned string may contain percent escapes. @par Example @code assert( url_view( "http://www.example.com/index.html?query#frag" ).encoded_resource() == "/index.html?query#frag" ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par Specification @li 3.3. Path (rfc3986) @li 3.4. Query (rfc3986) @see @ref encoded_origin, @ref encoded_target. @return The resource portion of the url. */ pct_string_view encoded_resource() const noexcept; /** Return the target This function returns the target, which is the portion of the url that includes only the path and query. The returned string may contain percent escapes. @par Example @code assert( url_view( "http://www.example.com/index.html?query#frag" ).encoded_target() == "/index.html?query" ); @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @par Specification @li 3.3. Path (rfc3986) @li 3.4. Query (rfc3986) @see @ref encoded_origin, @ref encoded_resource. @return The target portion of the url. */ pct_string_view encoded_target() const noexcept; //-------------------------------------------- // // Comparison // //-------------------------------------------- /** Return the result of comparing this with another url This function compares two URLs according to Syntax-Based comparison algorithm. @par Complexity Linear in `min( u0.size(), u1.size() )` @par Exception Safety Throws nothing. @par Specification @li 6.2.2 Syntax-Based Normalization (rfc3986) @param other The url to compare @return -1 if `*this < other`, 0 if `this == other`, and 1 if `this > other`. */ int compare(url_view_base const& other) const noexcept; /** Return the result of comparing two URLs The URLs are compared component by component as if they were first normalized. @par Example @code url_view u0( "http://www.a.com/index.htm" ); url_view u1( "http://www.a.com/index.htm" ); assert( u0 == u1 ); @endcode @par Effects @code url a(u0); a.normalize(); url b(u1); b.normalize(); return a.buffer() == b.buffer(); @endcode @par Complexity Linear in `min( u0.size(), u1.size() )` @par Exception Safety Throws nothing @param u0 The first url to compare @param u1 The second url to compare @return `true` if `u0 == u1` @par Specification @li 6.2.2 Syntax-Based Normalization (rfc3986) */ friend bool operator==( url_view_base const& u0, url_view_base const& u1) noexcept { return u0.compare(u1) == 0; } /** Return the result of comparing two URLs The URLs are compared component by component as if they were first normalized. @par Example @code url_view u0( "http://www.a.com/index.htm" ); url_view u1( "http://www.b.com/index.htm" ); assert( u0 != u1 ); @endcode @par Effects @code url a(u0); a.normalize(); url b(u1); b.normalize(); return a.buffer() != b.buffer(); @endcode @par Complexity Linear in `min( u0.size(), u1.size() )` @par Exception Safety Throws nothing @param u0 The first url to compare @param u1 The second url to compare @return `true` if `u0 != u1` @par Specification @li 6.2.2 Syntax-Based Normalization (rfc3986) */ friend bool operator!=( url_view_base const& u0, url_view_base const& u1) noexcept { return ! (u0 == u1); } /** Return the result of comparing two URLs The URLs are compared component by component as if they were first normalized. @par Example @code url_view u0( "http://www.a.com/index.htm" ); url_view u1( "http://www.b.com/index.htm" ); assert( u0 < u1 ); @endcode @par Effects @code url a(u0); a.normalize(); url b(u1); b.normalize(); return a.buffer() < b.buffer(); @endcode @par Complexity Linear in `min( u0.size(), u1.size() )` @par Exception Safety Throws nothing @param u0 The first url to compare @param u1 The second url to compare @return `true` if `u0 < u1` @par Specification @li 6.2.2 Syntax-Based Normalization (rfc3986) */ friend bool operator<( url_view_base const& u0, url_view_base const& u1) noexcept { return u0.compare(u1) < 0; } /** Return the result of comparing two URLs The URLs are compared component by component as if they were first normalized. @par Example @code url_view u0( "http://www.b.com/index.htm" ); url_view u1( "http://www.b.com/index.htm" ); assert( u0 <= u1 ); @endcode @par Effects @code url a(u0); a.normalize(); url b(u1); b.normalize(); return a.buffer() <= b.buffer(); @endcode @par Complexity Linear in `min( u0.size(), u1.size() )` @par Exception Safety Throws nothing @param u0 The first url to compare @param u1 The second url to compare @return `true` if `u0 <= u1` @par Specification @li 6.2.2 Syntax-Based Normalization (rfc3986) */ friend bool operator<=( url_view_base const& u0, url_view_base const& u1) noexcept { return u0.compare(u1) <= 0; } /** Return the result of comparing two URLs The URLs are compared component by component as if they were first normalized. @par Example @code url_view u0( "http://www.b.com/index.htm" ); url_view u1( "http://www.a.com/index.htm" ); assert( u0 > u1 ); @endcode @par Effects @code url a(u0); a.normalize(); url b(u1); b.normalize(); return a.buffer() > b.buffer(); @endcode @par Complexity Linear in `min( u0.size(), u1.size() )` @par Exception Safety Throws nothing @param u0 The first url to compare @param u1 The second url to compare @return `true` if `u0 > u1` @par Specification @li 6.2.2 Syntax-Based Normalization (rfc3986) */ friend bool operator>( url_view_base const& u0, url_view_base const& u1) noexcept { return u0.compare(u1) > 0; } /** Return the result of comparing two URLs The URLs are compared component by component as if they were first normalized. @par Example @code url_view u0( "http://www.a.com/index.htm" ); url_view u1( "http://www.a.com/index.htm" ); assert( u0 >= u1 ); @endcode @par Effects @code url a(u0); a.normalize(); url b(u1); b.normalize(); return a.buffer() >= b.buffer(); @endcode @par Complexity Linear in `min( u0.size(), u1.size() )` @par Exception Safety Throws nothing @param u0 The first url to compare @param u1 The second url to compare @return `true` if `u0 >= u1` @par Specification @li 6.2.2 Syntax-Based Normalization (rfc3986) */ friend bool operator>=( url_view_base const& u0, url_view_base const& u1) noexcept { return u0.compare(u1) >= 0; } /** Format the url to the output stream This function serializes the url to the specified output stream. Any percent-escapes are emitted as-is; no decoding is performed. @par Example @code url_view u( "http://www.example.com/index.htm" ); std::stringstream ss; ss << u; assert( ss.str() == "http://www.example.com/index.htm" ); @endcode @par Effects @code return os << u.buffer(); @endcode @par Complexity Linear in `u.buffer().size()` @par Exception Safety Basic guarantee. @return A reference to the output stream, for chaining @param os The output stream to write to. @param u The url to write. */ friend std::ostream& operator<<( std::ostream& os, url_view_base const& u) { return os << u.buffer(); } private: //-------------------------------------------- // // implementation // //-------------------------------------------- static int segments_compare( segments_encoded_view seg0, segments_encoded_view seg1) noexcept; }; //------------------------------------------------ /** Format the url to the output stream This function serializes the url to the specified output stream. Any percent-escapes are emitted as-is; no decoding is performed. @par Example @code url_view u( "http://www.example.com/index.htm" ); std::stringstream ss; ss << u; assert( ss.str() == "http://www.example.com/index.htm" ); @endcode @par Effects @code return os << u.buffer(); @endcode @par Complexity Linear in `u.buffer().size()` @par Exception Safety Basic guarantee. @return A reference to the output stream, for chaining @param os The output stream to write to. @param u The url to write. */ std::ostream& operator<<( std::ostream& os, url_view_base const& u); } // urls } // boost #endif