123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547 |
- //
- // Copyright (c) 2019 Vinnie Falco ([email protected])
- // Copyright (c) 2022 Alan de Freitas ([email protected])
- //
- // 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_HPP
- #define BOOST_URL_URL_HPP
- #include <boost/url/detail/config.hpp>
- #include <boost/url/url_base.hpp>
- #include <boost/assert.hpp>
- #include <utility>
- namespace boost {
- namespace urls {
- /** A modifiable container for a URL.
- This container owns a url, represented
- by a null-terminated character buffer
- which is managed by performing dymamic
- memory allocations as needed.
- The contents may be inspected and modified,
- and the implementation maintains a useful
- invariant: changes to the url always
- leave it in a valid state.
- @par Exception Safety
- @li Functions marked `noexcept` provide the
- no-throw guarantee, otherwise:
- @li Functions which throw offer the strong
- exception safety guarantee.
- @par BNF
- @code
- URI-reference = URI / relative-ref
- URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
- relative-ref = relative-part [ "?" query ] [ "#" fragment ]
- absolute-URI = scheme ":" hier-part [ "?" query ]
- @endcode
- @par Specification
- @li <a href="https://tools.ietf.org/html/rfc3986"
- >Uniform Resource Identifier (URI): Generic Syntax (rfc3986)</a>
- @see
- @ref parse_absolute_uri,
- @ref parse_relative_ref,
- @ref parse_uri,
- @ref parse_uri_reference,
- @ref resolve.
- */
- class BOOST_URL_DECL url
- : public url_base
- {
- friend std::hash<url>;
- using url_view_base::digest;
- public:
- //--------------------------------------------
- //
- // Special Members
- //
- //--------------------------------------------
- /** Destructor
- Any params, segments, iterators, or
- views which reference this object are
- invalidated. The underlying character
- buffer is destroyed, invalidating all
- references to it.
- */
- virtual ~url();
- /** Constructor
- Default constructed urls contain
- a zero-length string. This matches
- the grammar for a relative-ref with
- an empty path and no query or
- fragment.
- @par Example
- @code
- url u;
- @endcode
- @par Postconditions
- @code
- this->empty() == true
- @endcode
- @par Complexity
- Constant.
- @par Exception Safety
- Throws nothing.
- @par BNF
- @code
- relative-ref = relative-part [ "?" query ] [ "#" fragment ]
- @endcode
- @par Specification
- <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.2"
- >4.2. Relative Reference (rfc3986)</a>
- */
- url() noexcept;
- /** Constructor
- This function constructs a URL from
- the string `s`, which must contain a
- valid <em>URI</em> or <em>relative-ref</em>
- or else an exception is thrown.
- The new url retains ownership by
- allocating a copy of the passed string.
- @par Example
- @code
- url u( "https://www.example.com" );
- @endcode
- @par Effects
- @code
- return url( parse_uri_reference( s ).value() );
- @endcode
- @par Postconditions
- @code
- this->buffer().data() != s.data()
- @endcode
- @par Complexity
- Linear in `s.size()`.
- @par Exception Safety
- Calls to allocate may throw.
- Exceptions thrown on invalid input.
- @throw system_error
- The input does not contain a valid url.
- @param s The string to parse.
- @par BNF
- @code
- URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
- relative-ref = relative-part [ "?" query ] [ "#" fragment ]
- @endcode
- @par Specification
- @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.1"
- >4.1. URI Reference</a>
- */
- explicit
- url(core::string_view s);
- /** Constructor
- The contents of `u` are transferred
- to the newly constructed object,
- which includes the underlying
- character buffer.
- After construction, the moved-from
- object is as if default constructed.
- @par Postconditions
- @code
- u.empty() == true
- @endcode
- @par Complexity
- Constant.
- @par Exception Safety
- Throws nothing.
- @param u The url to move from.
- */
- url(url&& u) noexcept;
- /** Constructor
- The newly constructed object
- contains a copy of `u`.
- @par Postconditions
- @code
- this->buffer() == u.buffer() && this->buffer().data() != u.buffer().data()
- @endcode
- @par Complexity
- Linear in `u.size()`.
- @par Exception Safety
- Strong guarantee.
- Calls to allocate may throw.
- @throw std::length_error `u.size() > max_size()`.
- @param u The url to copy.
- */
- url(url_view_base const& u)
- {
- copy(u);
- }
- /** Constructor
- The newly constructed object
- contains a copy of `u`.
- @par Postconditions
- @code
- this->buffer() == u.buffer() && this->buffer().data() != u.buffer().data()
- @endcode
- @par Complexity
- Linear in `u.size()`.
- @par Exception Safety
- Strong guarantee.
- Calls to allocate may throw.
- @throw std::length_error `u.size() > max_size()`.
- @param u The url to copy.
- */
- url(url const& u)
- : url(static_cast<
- url_view_base const&>(u))
- {
- }
- /** Assignment
- The contents of `u` are transferred to
- `this`, including the underlying
- character buffer. The previous contents
- of `this` are destroyed.
- After assignment, the moved-from
- object is as if default constructed.
- @par Postconditions
- @code
- u.empty() == true
- @endcode
- @par Complexity
- Constant.
- @par Exception Safety
- Throws nothing.
- @param u The url to assign from.
- */
- url&
- operator=(url&& u) noexcept;
- /** Assignment
- The contents of `u` are copied and
- the previous contents of `this` are
- destroyed.
- Capacity is preserved, or increases.
- @par Postconditions
- @code
- this->buffer() == u.buffer() && this->buffer().data() != u.buffer().data()
- @endcode
- @par Complexity
- Linear in `u.size()`.
- @par Exception Safety
- Strong guarantee.
- Calls to allocate may throw.
- @throw std::length_error `u.size() > max_size()`.
- @param u The url to copy.
- */
- url&
- operator=(
- url_view_base const& u)
- {
- copy(u);
- return *this;
- }
- /** Assignment
- The contents of `u` are copied and
- the previous contents of `this` are
- destroyed.
- Capacity is preserved, or increases.
- @par Postconditions
- @code
- this->buffer() == u.buffer() && this->buffer().data() != u.buffer().data()
- @endcode
- @par Complexity
- Linear in `u.size()`.
- @par Exception Safety
- Strong guarantee.
- Calls to allocate may throw.
- @param u The url to copy.
- */
- url&
- operator=(url const& u)
- {
- return (*this)=static_cast<
- url_view_base const&>(u);
- }
- //--------------------------------------------
- /** Swap the contents.
- Exchanges the contents of this url with another
- url. All views, iterators and references remain valid.
- If `this == &other`, this function call has no effect.
- @par Example
- @code
- url u1( "https://www.example.com" );
- url u2( "https://www.boost.org" );
- u1.swap(u2);
- assert(u1 == "https://www.boost.org" );
- assert(u2 == "https://www.example.com" );
- @endcode
- @par Complexity
- Constant
- @par Exception Safety
- Throws nothing.
- @param other The object to swap with
- */
- void
- swap(url& other) noexcept;
- /** Swap
- Exchanges the contents of `v0` with another `v1`.
- All views, iterators and references remain
- valid.
- If `&v0 == &v1`, this function call has no effect.
- @par Example
- @code
- url u1( "https://www.example.com" );
- url u2( "https://www.boost.org" );
- std::swap(u1, u2);
- assert(u1 == "https://www.boost.org" );
- assert(u2 == "https://www.example.com" );
- @endcode
- @par Effects
- @code
- v0.swap( v1 );
- @endcode
- @par Complexity
- Constant
- @par Exception Safety
- Throws nothing
- @param v0, v1 The objects to swap
- @see
- @ref url::swap
- */
- friend
- void
- swap(url& v0, url& v1) noexcept
- {
- v0.swap(v1);
- }
- //--------------------------------------------
- //
- // fluent api
- //
- /// @copydoc url_base::set_scheme
- url& set_scheme(core::string_view s) { url_base::set_scheme(s); return *this; }
- /// @copydoc url_base::set_scheme_id
- url& set_scheme_id(urls::scheme id) { url_base::set_scheme_id(id); return *this; }
- /// @copydoc url_base::remove_scheme
- url& remove_scheme() { url_base::remove_scheme(); return *this; }
- /// @copydoc url_base::set_encoded_authority
- url& set_encoded_authority(pct_string_view s) { url_base::set_encoded_authority(s); return *this; }
- /// @copydoc url_base::remove_authority
- url& remove_authority() { url_base::remove_authority(); return *this; }
- /// @copydoc url_base::set_userinfo
- url& set_userinfo(core::string_view s) { url_base::set_userinfo(s); return *this; }
- /// @copydoc url_base::set_encoded_userinfo
- url& set_encoded_userinfo(pct_string_view s) { url_base::set_encoded_userinfo(s); return *this; }
- /// @copydoc url_base::remove_userinfo
- url& remove_userinfo() noexcept { url_base::remove_userinfo(); return *this; }
- /// @copydoc url_base::set_user
- url& set_user(core::string_view s) { url_base::set_user(s); return *this; }
- /// @copydoc url_base::set_encoded_user
- url& set_encoded_user(pct_string_view s) { url_base::set_encoded_user(s); return *this; }
- /// @copydoc url_base::set_password
- url& set_password(core::string_view s) { url_base::set_password(s); return *this; }
- /// @copydoc url_base::set_encoded_password
- url& set_encoded_password(pct_string_view s) { url_base::set_encoded_password(s); return *this; }
- /// @copydoc url_base::remove_password
- url& remove_password() noexcept { url_base::remove_password(); return *this; }
- /// @copydoc url_base::set_host
- url& set_host(core::string_view s) { url_base::set_host(s); return *this; }
- /// @copydoc url_base::set_encoded_host
- url& set_encoded_host(pct_string_view s) { url_base::set_encoded_host(s); return *this; }
- /// @copydoc url_base::set_host_address
- url& set_host_address(core::string_view s) { url_base::set_host_address(s); return *this; }
- /// @copydoc url_base::set_encoded_host_address
- url& set_encoded_host_address(pct_string_view s) { url_base::set_encoded_host_address(s); return *this; }
- /// @copydoc url_base::set_host_ipv4
- url& set_host_ipv4(ipv4_address const& addr) { url_base::set_host_ipv4(addr); return *this; }
- /// @copydoc url_base::set_host_ipv6
- url& set_host_ipv6(ipv6_address const& addr) { url_base::set_host_ipv6(addr); return *this; }
- /// @copydoc url_base::set_host_ipvfuture
- url& set_host_ipvfuture(core::string_view s) { url_base::set_host_ipvfuture(s); return *this; }
- /// @copydoc url_base::set_host_name
- url& set_host_name(core::string_view s) { url_base::set_host_name(s); return *this; }
- /// @copydoc url_base::set_encoded_host_name
- url& set_encoded_host_name(pct_string_view s) { url_base::set_encoded_host_name(s); return *this; }
- /// @copydoc url_base::set_port_number
- url& set_port_number(std::uint16_t n) { url_base::set_port_number(n); return *this; }
- /// @copydoc url_base::set_port
- url& set_port(core::string_view s) { url_base::set_port(s); return *this; }
- /// @copydoc url_base::remove_port
- url& remove_port() noexcept { url_base::remove_port(); return *this; }
- /// @copydoc url_base::set_path_absolute
- //bool set_path_absolute(bool absolute);
- /// @copydoc url_base::set_path
- url& set_path(core::string_view s) { url_base::set_path(s); return *this; }
- /// @copydoc url_base::set_encoded_path
- url& set_encoded_path(pct_string_view s) { url_base::set_encoded_path(s); return *this; }
- /// @copydoc url_base::set_query
- url& set_query(core::string_view s) { url_base::set_query(s); return *this; }
- /// @copydoc url_base::set_encoded_query
- url& set_encoded_query(pct_string_view s) { url_base::set_encoded_query(s); return *this; }
- /// @copydoc url_base::set_params
- url& set_params(std::initializer_list<param_view> ps) { url_base::set_params(ps); return *this; }
- /// @copydoc url_base::set_encoded_params
- url& set_encoded_params(std::initializer_list< param_pct_view > ps) { url_base::set_encoded_params(ps); return *this; }
- /// @copydoc url_base::remove_query
- url& remove_query() noexcept { url_base::remove_query(); return *this; }
- /// @copydoc url_base::remove_fragment
- url& remove_fragment() noexcept { url_base::remove_fragment(); return *this; }
- /// @copydoc url_base::set_fragment
- url& set_fragment(core::string_view s) { url_base::set_fragment(s); return *this; }
- /// @copydoc url_base::set_encoded_fragment
- url& set_encoded_fragment(pct_string_view s) { url_base::set_encoded_fragment(s); return *this; }
- /// @copydoc url_base::remove_origin
- url& remove_origin() { url_base::remove_origin(); return *this; }
- /// @copydoc url_base::normalize
- url& normalize() { url_base::normalize(); return *this; }
- /// @copydoc url_base::normalize_scheme
- url& normalize_scheme() { url_base::normalize_scheme(); return *this; }
- /// @copydoc url_base::normalize_authority
- url& normalize_authority() { url_base::normalize_authority(); return *this; }
- /// @copydoc url_base::normalize_path
- url& normalize_path() { url_base::normalize_path(); return *this; }
- /// @copydoc url_base::normalize_query
- url& normalize_query() { url_base::normalize_query(); return *this; }
- /// @copydoc url_base::normalize_fragment
- url& normalize_fragment() { url_base::normalize_fragment(); return *this; }
- //--------------------------------------------
- private:
- char* allocate(std::size_t);
- void deallocate(char* s);
- void clear_impl() noexcept override;
- void reserve_impl(std::size_t, op_t&) override;
- void cleanup(op_t&) override;
- };
- } // urls
- } // boost
- //------------------------------------------------
- // std::hash specialization
- #ifndef BOOST_URL_DOCS
- namespace std {
- template<>
- struct hash< ::boost::urls::url >
- {
- hash() = default;
- hash(hash const&) = default;
- hash& operator=(hash const&) = default;
- explicit
- hash(std::size_t salt) noexcept
- : salt_(salt)
- {
- }
- std::size_t
- operator()(::boost::urls::url const& u) const noexcept
- {
- return u.digest(salt_);
- }
- private:
- std::size_t salt_ = 0;
- };
- } // std
- #endif
- #endif
|