// // 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_PARAMS_REF_HPP #define BOOST_URL_PARAMS_REF_HPP #include #include #include #include #include namespace boost { namespace urls { #ifndef BOOST_URL_DOCS class url_base; class params_view; #endif /** A view representing query parameters in a URL Objects of this type are used to interpret the query parameters as a bidirectional view of key/value pairs. The view does not retain ownership of the elements and instead references the original url. The caller is responsible for ensuring that the lifetime of the referenced url extends until it is no longer referenced. The view is modifiable; calling non-const members causes changes to the referenced url.
Percent escapes in strings returned when dereferencing iterators are automatically decoded. Reserved characters in strings supplied to modifier functions are automatically percent-escaped. @par Example @code url u( "?first=John&last=Doe" ); params_ref p = u.params(); @endcode @par Iterator Invalidation Changes to the underlying character buffer can invalidate iterators which reference it. Modifications made through the container invalidate some or all iterators:
@li @ref append : Only `end()`. @li @ref assign, @ref clear, `operator=` : All elements. @li @ref erase : Erased elements and all elements after (including `end()`). @li @ref insert : All elements at or after the insertion point (including `end()`). @li @ref replace, @ref set : Modified elements and all elements after (including `end()`). */ class params_ref : public params_base { friend class url_base; url_base* u_ = nullptr; params_ref( url_base& u, encoding_opts opt) noexcept; public: //-------------------------------------------- // // Special Members // //-------------------------------------------- /** Constructor After construction, both views reference the same url. Ownership is not transferred; the caller is responsible for ensuring the lifetime of the url extends until it is no longer referenced. @par Postconditions @code &this->url() == &other.url() @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @param other The other view. */ params_ref( params_ref const& other) = default; /** Constructor After construction, both views will reference the same url but this instance will use the specified @ref encoding_opts when the values are decoded. Ownership is not transferred; the caller is responsible for ensuring the lifetime of the url extends until it is no longer referenced. @par Postconditions @code &this->url() == &other.url() @endcode @par Complexity Constant. @par Exception Safety Throws nothing. @param other The other view. @param opt The options for decoding. If this parameter is omitted, `space_as_plus` is used. */ params_ref( params_ref const& other, encoding_opts opt) noexcept; /** Assignment The previous contents of this are replaced by the contents of `other.
All iterators are invalidated. @note The strings referenced by `other` must not come from the underlying url, or else the behavior is undefined. @par Effects @code this->assign( other.begin(), other.end() ); @endcode @par Complexity Linear in `other.buffer().size()`. @par Exception Safety Strong guarantee. Calls to allocate may throw. @param other The params to assign. */ BOOST_URL_DECL params_ref& operator=( params_ref const& other); /** Assignment After assignment, the previous contents of the query parameters are replaced by the contents of the initializer-list. @par Preconditions None of character buffers referenced by `init` may overlap the character buffer of the underlying url, or else the behavior is undefined. @par Effects @code this->assign( init ); @endcode @par Complexity Linear in `init.size()`. @par Exception Safety Strong guarantee. Calls to allocate may throw. @param init The list of params to assign. */ params_ref& operator=( std::initializer_list< param_view> init); /** Conversion */ BOOST_URL_DECL operator params_view() const noexcept; //-------------------------------------------- // // Observers // //-------------------------------------------- /** Return the referenced url This function returns the url referenced by the view. @par Example @code url u( "?key=value" ); assert( &u.segments().url() == &u ); @endcode @par Exception Safety @code Throws nothing. @endcode */ url_base& url() const noexcept { return *u_; } //-------------------------------------------- // // Modifiers // //-------------------------------------------- /** Clear the contents of the container
All iterators are invalidated. @par Effects @code this->url().remove_query(); @endcode @par Postconditions @code this->empty() == true && this->url().has_query() == false @endcode @par Complexity Constant. @par Exception Safety Throws nothing. */ void clear() noexcept; //-------------------------------------------- /** Assign elements This function replaces the entire contents of the view with the params in the initializer-list.
All iterators are invalidated. @note The strings referenced by the inputs must not come from the underlying url, or else the behavior is undefined. @par Example @code url u; u.params().assign( {{ "first", "John" }, { "last", "Doe" }} ); @endcode @par Complexity Linear in `init.size()`. @par Exception Safety Strong guarantee. Calls to allocate may throw. @param init The list of params to assign. */ BOOST_URL_DECL void assign( std::initializer_list< param_view> init); /** Assign elements This function replaces the entire contents of the view with the params in the range.
All iterators are invalidated. @note The strings referenced by the inputs must not come from the underlying url, or else the behavior is undefined. @par Mandates @code std::is_convertible< std::iterator_traits< FwdIt >::reference_type, param_view >::value == true @endcode @par Complexity Linear in the size of the range. @par Exception Safety Strong guarantee. Calls to allocate may throw. @param first, last The range of params to assign. */ template void assign(FwdIt first, FwdIt last); //-------------------------------------------- /** Append elements This function appends a param to the view.
The `end()` iterator is invalidated. @par Example @code url u; u.params().append( { "first", "John" } ); @endcode @par Complexity Linear in `this->url().encoded_query().size()`. @par Exception Safety Strong guarantee. Calls to allocate may throw. @return An iterator to the new element. @param p The param to append. */ iterator append( param_view const& p); /** Append elements This function appends the params in an initializer-list to the view.
The `end()` iterator is invalidated. @par Example @code url u; u.params().append({ { "first", "John" }, { "last", "Doe" } }); @endcode @par Complexity Linear in `this->url().encoded_query().size()`. @par Exception Safety Strong guarantee. Calls to allocate may throw. @return An iterator to the first new element. @param init The list of params to append. */ iterator append( std::initializer_list< param_view> init); /** Append elements This function appends a range of params to the view.
The `end()` iterator is invalidated. @note The strings referenced by the inputs must not come from the underlying url, or else the behavior is undefined. @par Mandates @code std::is_convertible< std::iterator_traits< FwdIt >::reference_type, param_view >::value == true @endcode @par Complexity Linear in `this->url().encoded_query().size()`. @par Exception Safety Strong guarantee. Calls to allocate may throw. @return An iterator to the first new element. @param first, last The range of params to append. */ template iterator append( FwdIt first, FwdIt last); //-------------------------------------------- /** Insert elements This function inserts a param before the specified position.
All iterators that are equal to `before` or come after are invalidated. @par Complexity Linear in `this->url().encoded_query().size()`. @par Exception Safety Strong guarantee. Calls to allocate may throw. @return An iterator to the inserted element. @param before An iterator before which the param is inserted. This may be equal to `end()`. @param p The param to insert. */ BOOST_URL_DECL iterator insert( iterator before, param_view const& p); /** Insert elements This function inserts the params in an initializer-list before the specified position.
All iterators that are equal to `before` or come after are invalidated. @note The strings referenced by the inputs must not come from the underlying url, or else the behavior is undefined. @par Complexity Linear in `this->url().encoded_query().size()`. @par Exception Safety Strong guarantee. Calls to allocate may throw. @return An iterator to the first element inserted, or `before` if `init.size() == 0`. @param before An iterator before which the element is inserted. This may be equal to `end()`. @param init The list of params to insert. */ BOOST_URL_DECL iterator insert( iterator before, std::initializer_list< param_view> init); /** Insert elements This function inserts a range of params before the specified position.
All iterators that are equal to `before` or come after are invalidated. @note The strings referenced by the inputs must not come from the underlying url, or else the behavior is undefined. @par Mandates @code std::is_convertible< std::iterator_traits< FwdIt >::reference_type, param_view >::value == true @endcode @par Complexity Linear in `this->url().encoded_query().size()`. @par Exception Safety Strong guarantee. Calls to allocate may throw. @return An iterator to the first element inserted, or `before` if `first == last`. @param before An iterator before which the element is inserted. This may be equal to `end()`. @param first, last The range of params to insert. */ template iterator insert( iterator before, FwdIt first, FwdIt last); //-------------------------------------------- /** Erase elements This function removes an element from the container.
All iterators that are equal to `pos` or come after are invalidated. @par Example @code url u( "?first=John&last=Doe" ); params_ref::iterator it = u.params().erase( u.params().begin() ); assert( u.encoded_query() == "last=Doe" ); @endcode @par Complexity Linear in `this->url().encoded_query().size()`. @par Exception Safety Throws nothing. @return An iterator to one past the removed element. @param pos An iterator to the element. */ iterator erase(iterator pos) noexcept; /** Erase elements This function removes a range of elements from the container.
All iterators that are equal to `first` or come after are invalidated. @par Complexity Linear in `this->url().encoded_query().size()`. @par Exception Safety Throws nothing. @return An iterator to one past the removed range. @param first, last The range of elements to erase. */ iterator erase( iterator first, iterator last) noexcept; /** Erase elements
All iterators are invalidated. @par Postconditions @code this->count( key, ic ) == 0 @endcode @par Complexity Linear in `this->url().encoded_query().size()`. @par Exception Safety Throws nothing. @return The number of elements removed from the container. @param key The key to match. By default, a case-sensitive comparison is used. @param ic An optional parameter. If the value @ref ignore_case is passed here, the comparison is case-insensitive. */ BOOST_URL_DECL std::size_t erase( string_view key, ignore_case_param ic = {}) noexcept; //-------------------------------------------- /** Replace elements This function replaces the contents of the element at `pos` with the specified param.
All iterators that are equal to `pos` or come after are invalidated. @par Example @code url u( "?first=John&last=Doe" ); u.params().replace( u.params().begin(), { "title", "Mr" }); assert( u.encoded_query() == "title=Mr&last=Doe" ); @endcode @par Complexity Linear in `this->url().encoded_query().size()`. @par Exception Safety Strong guarantee. Calls to allocate may throw. @return An iterator to the element. @param pos An iterator to the element. @param p The param to assign. */ BOOST_URL_DECL iterator replace( iterator pos, param_view const& p); /** Replace elements This function replaces a range of elements with the params in an initializer-list.
All iterators that are equal to `from` or come after are invalidated. @note The strings referenced by the inputs must not come from the underlying url, or else the behavior is undefined. @par Complexity Linear in `this->url().encoded_query().size()`. @par Exception Safety Strong guarantee. Calls to allocate may throw. @return An iterator to the first element inserted, or one past `to` if `init.size() == 0`. @param from,to The range of elements to replace. @param init The list of params to assign. */ BOOST_URL_DECL iterator replace( iterator from, iterator to, std::initializer_list< param_view> init); /** Replace elements This function replaces a range of elements with a range of params.
All iterators that are equal to `from` or come after are invalidated. @note The strings referenced by the inputs must not come from the underlying url, or else the behavior is undefined. @par Mandates @code std::is_convertible< std::iterator_traits< FwdIt >::reference_type, param_view >::value == true @endcode @par Complexity Linear in `this->url().encoded_query().size()`. @par Exception Safety Strong guarantee. Calls to allocate may throw. @return An iterator to the first element inserted, or one past `to` if `first == last`. @param from,to The range of elements to replace. @param first, last The range of params to assign. */ template iterator replace( iterator from, iterator to, FwdIt first, FwdIt last); //-------------------------------------------- /** Remove the value on an element This function removes the value of an element at the specified position. After the call returns, `has_value` for the element is false.
All iterators that are equal to `pos` or come after are invalidated. @par Example @code url u( "?first=John&last=Doe" ); u.params().unset( u.params().begin() ); assert( u.encoded_query() == "first&last=Doe" ); @endcode @par Complexity Linear in `this->url().encoded_query().size()`. @par Exception Safety Throws nothing. @return An iterator to the element. @param pos An iterator to the element. */ BOOST_URL_DECL iterator unset( iterator pos) noexcept; /** Set a value This function replaces the value of an element at the specified position.
All iterators that are equal to `pos` or come after are invalidated. @par Example @code url u( "?id=42&id=69" ); u.params().set( u.params().begin(), "none" ); assert( u.encoded_query() == "id=none&id=69" ); @endcode @par Complexity Linear in `this->url().encoded_query().size()`. @par Exception Safety Strong guarantee. Calls to allocate may throw. @return An iterator to the element. @param pos An iterator to the element. @param value The value to assign. The empty string still counts as a value. That is, `has_value` for the element is true. */ BOOST_URL_DECL iterator set( iterator pos, string_view value); /** Set a value This function performs one of two actions depending on the value of `this->contains( key, ic )`. @li If key is contained in the view then one of the matching elements has its value changed to the specified value. The remaining elements with a matching key are erased. Otherwise, @li If `key` is not contained in the view, then the function apppends the param `{ key, value }`.
All iterators are invalidated. @par Example @code url u( "?id=42&id=69" ); u.params().set( "id", "none" ); assert( u.params().count( "id" ) == 1 ); @endcode @par Postconditions @code this->count( key, ic ) == 1 && this->find( key, ic )->value == value @endcode @par Complexity Linear in `this->url().encoded_query().size()`. @par Exception Safety Strong guarantee. Calls to allocate may throw. @return An iterator to the appended or modified element. @param key The key to match. By default, a case-sensitive comparison is used. @param value The value to assign. The empty string still counts as a value. That is, `has_value` for the element is true. @param ic An optional parameter. If the value @ref ignore_case is passed here, the comparison is case-insensitive. */ BOOST_URL_DECL iterator set( string_view key, string_view value, ignore_case_param ic = {}); //-------------------------------------------- private: BOOST_URL_DECL detail::params_iter_impl find_impl( detail::params_iter_impl, string_view, ignore_case_param) const noexcept; BOOST_URL_DECL detail::params_iter_impl find_last_impl( detail::params_iter_impl, string_view, ignore_case_param) const noexcept; template void assign(FwdIt first, FwdIt last, std::forward_iterator_tag); // Doxygen cannot render ` = delete` template void assign(FwdIt first, FwdIt last, std::input_iterator_tag) = delete; template iterator insert( iterator before, FwdIt first, FwdIt last, std::forward_iterator_tag); // Doxygen cannot render ` = delete` template iterator insert( iterator before, FwdIt first, FwdIt last, std::input_iterator_tag) = delete; }; } // urls } // boost // This is in // // #include #endif