520 lines
13 KiB
C++
520 lines
13 KiB
C++
|
//
|
||
|
// 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_BASE_HPP
|
||
|
#define BOOST_URL_PARAMS_BASE_HPP
|
||
|
|
||
|
#include <boost/url/detail/config.hpp>
|
||
|
#include <boost/url/encoding_opts.hpp>
|
||
|
#include <boost/url/ignore_case.hpp>
|
||
|
#include <boost/url/param.hpp>
|
||
|
#include <boost/url/detail/params_iter_impl.hpp>
|
||
|
#include <boost/url/detail/url_impl.hpp>
|
||
|
#include <iosfwd>
|
||
|
|
||
|
namespace boost {
|
||
|
namespace urls {
|
||
|
|
||
|
/** 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 params_ref
|
||
|
@li @ref params_view
|
||
|
@li @ref params_encoded_ref
|
||
|
@li @ref params_encoded_view
|
||
|
*/
|
||
|
class BOOST_URL_DECL params_base
|
||
|
{
|
||
|
friend class url_view_base;
|
||
|
friend class params_ref;
|
||
|
friend class params_view;
|
||
|
|
||
|
detail::query_ref ref_;
|
||
|
encoding_opts opt_;
|
||
|
|
||
|
params_base() noexcept;
|
||
|
params_base(
|
||
|
detail::query_ref const& ref,
|
||
|
encoding_opts opt) noexcept;
|
||
|
params_base(
|
||
|
params_base const&) = default;
|
||
|
params_base& operator=(
|
||
|
params_base const&) = default;
|
||
|
|
||
|
public:
|
||
|
/** A Bidirectional iterator to a query parameter
|
||
|
|
||
|
Objects of this type allow iteration
|
||
|
through the parameters in the query.
|
||
|
Any percent-escapes in returned strings
|
||
|
are decoded first.
|
||
|
The values returned are read-only;
|
||
|
changes to parameters must be made
|
||
|
through the container instead, if the
|
||
|
container supports modification.
|
||
|
|
||
|
<br>
|
||
|
|
||
|
The strings produced when iterators are
|
||
|
dereferenced belong to the iterator and
|
||
|
become invalidated when that particular
|
||
|
iterator is incremented, decremented,
|
||
|
or destroyed.
|
||
|
|
||
|
@note
|
||
|
|
||
|
The implementation may use temporary,
|
||
|
recycled storage to store decoded
|
||
|
strings. These iterators are meant
|
||
|
to be used ephemerally. That is, for
|
||
|
short durations such as within a
|
||
|
function scope. Do not store
|
||
|
iterators with static storage
|
||
|
duration or as long-lived objects.
|
||
|
*/
|
||
|
#ifdef BOOST_URL_DOCS
|
||
|
using iterator = __see_below__;
|
||
|
#else
|
||
|
class iterator;
|
||
|
#endif
|
||
|
|
||
|
/// @copydoc iterator
|
||
|
using const_iterator = iterator;
|
||
|
|
||
|
/** The value type
|
||
|
|
||
|
Values of this type represent parameters
|
||
|
whose strings retain unique ownership by
|
||
|
making a copy.
|
||
|
|
||
|
@par Example
|
||
|
@code
|
||
|
params_view::value_type qp( *url_view( "?first=John&last=Doe" ).params().find( "first" ) );
|
||
|
@endcode
|
||
|
|
||
|
@see
|
||
|
@ref param.
|
||
|
*/
|
||
|
using value_type = param;
|
||
|
|
||
|
/** The reference type
|
||
|
|
||
|
This is the type of value returned when
|
||
|
iterators of the view are dereferenced.
|
||
|
|
||
|
@see
|
||
|
@ref param_view.
|
||
|
*/
|
||
|
using reference = param;
|
||
|
|
||
|
/// @copydoc reference
|
||
|
using const_reference = param;
|
||
|
|
||
|
/** An unsigned integer type to represent sizes.
|
||
|
*/
|
||
|
using size_type = std::size_t;
|
||
|
|
||
|
/** A signed integer type used to represent differences.
|
||
|
*/
|
||
|
using difference_type = std::ptrdiff_t;
|
||
|
|
||
|
//--------------------------------------------
|
||
|
//
|
||
|
// Observers
|
||
|
//
|
||
|
//--------------------------------------------
|
||
|
|
||
|
/** Return the maximum number of characters possible
|
||
|
|
||
|
This represents the largest number of
|
||
|
characters that are possible in a path,
|
||
|
not including any null terminator.
|
||
|
|
||
|
@par Exception Safety
|
||
|
Throws nothing.
|
||
|
*/
|
||
|
static
|
||
|
constexpr
|
||
|
std::size_t
|
||
|
max_size() noexcept
|
||
|
{
|
||
|
return BOOST_URL_MAX_SIZE;
|
||
|
}
|
||
|
|
||
|
/** Return the referenced character buffer.
|
||
|
|
||
|
This function returns the character
|
||
|
buffer referenced by the view.
|
||
|
The returned string may contain
|
||
|
percent escapes.
|
||
|
|
||
|
@par Example
|
||
|
@code
|
||
|
assert( url_view( "?first=John&last=Doe" ).params().buffer() == "?first=John&last=Doe" );
|
||
|
@endcode
|
||
|
|
||
|
@par Complexity
|
||
|
Constant.
|
||
|
|
||
|
@par Exception Safety
|
||
|
Throws nothing.
|
||
|
*/
|
||
|
pct_string_view
|
||
|
buffer() const noexcept;
|
||
|
|
||
|
/** Return true if there are no params
|
||
|
|
||
|
@par Example
|
||
|
@code
|
||
|
assert( ! url_view( "?key=value" ).params().empty() );
|
||
|
@endcode
|
||
|
|
||
|
@par Complexity
|
||
|
Constant.
|
||
|
|
||
|
@par Exception Safety
|
||
|
Throws nothing.
|
||
|
*/
|
||
|
bool
|
||
|
empty() const noexcept;
|
||
|
|
||
|
/** Return the number of params
|
||
|
|
||
|
@par Example
|
||
|
@code
|
||
|
assert( url_view( "?key=value").params().size() == 1 );
|
||
|
@endcode
|
||
|
|
||
|
@par Complexity
|
||
|
Constant.
|
||
|
|
||
|
@par Exception Safety
|
||
|
Throws nothing.
|
||
|
*/
|
||
|
std::size_t
|
||
|
size() const noexcept;
|
||
|
|
||
|
/** Return an iterator to the beginning
|
||
|
|
||
|
@par Complexity
|
||
|
Linear in the size of the first param.
|
||
|
|
||
|
@par Exception Safety
|
||
|
Throws nothing.
|
||
|
*/
|
||
|
iterator
|
||
|
begin() const noexcept;
|
||
|
|
||
|
/** Return an iterator to the end
|
||
|
|
||
|
@par Complexity
|
||
|
Constant.
|
||
|
|
||
|
@par Exception Safety
|
||
|
Throws nothing.
|
||
|
*/
|
||
|
iterator
|
||
|
end() const noexcept;
|
||
|
|
||
|
//--------------------------------------------
|
||
|
|
||
|
/** Return true if a matching key exists
|
||
|
|
||
|
This function examines the parameters
|
||
|
in the container to find a match for
|
||
|
the specified key.
|
||
|
The comparison is performed as if all
|
||
|
escaped characters were decoded first.
|
||
|
|
||
|
@par Example
|
||
|
@code
|
||
|
assert( url_view( "?first=John&last=Doe" ).params().contains( "first" ) );
|
||
|
@endcode
|
||
|
|
||
|
@par Complexity
|
||
|
Linear in `this->buffer().size()`.
|
||
|
|
||
|
@par Exception Safety
|
||
|
Throws nothing.
|
||
|
|
||
|
@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.
|
||
|
*/
|
||
|
bool
|
||
|
contains(
|
||
|
core::string_view key,
|
||
|
ignore_case_param ic = {}) const noexcept;
|
||
|
|
||
|
/** Return the number of matching keys
|
||
|
|
||
|
This function examines the
|
||
|
parameters in the container to
|
||
|
find the number of matches for
|
||
|
the specified key.
|
||
|
The comparison is performed as if all
|
||
|
escaped characters were decoded first.
|
||
|
|
||
|
@par Example
|
||
|
@code
|
||
|
assert( url_view( "?first=John&last=Doe" ).params().count( "first" ) == 1 );
|
||
|
@endcode
|
||
|
|
||
|
@par Complexity
|
||
|
Linear in `this->buffer().size()`.
|
||
|
|
||
|
@par Exception Safety
|
||
|
Throws nothing.
|
||
|
|
||
|
@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.
|
||
|
*/
|
||
|
std::size_t
|
||
|
count(
|
||
|
core::string_view key,
|
||
|
ignore_case_param ic = {}) const noexcept;
|
||
|
|
||
|
/** Find a matching key
|
||
|
|
||
|
This function examines the parameters
|
||
|
in the container to find a match for
|
||
|
the specified key.
|
||
|
The comparison is performed as if all
|
||
|
escaped characters were decoded first.
|
||
|
|
||
|
<br>
|
||
|
|
||
|
The search starts from the first param
|
||
|
and proceeds forward until either the
|
||
|
key is found or the end of the range is
|
||
|
reached, in which case `end()` is
|
||
|
returned.
|
||
|
|
||
|
@par Example
|
||
|
@code
|
||
|
assert( (*url_view( "?first=John&last=Doe" ).params().find( "First", ignore_case )).value == "John" );
|
||
|
@endcode
|
||
|
|
||
|
@par Effects
|
||
|
@code
|
||
|
return this->find( this->begin(), key, ic );
|
||
|
@endcode
|
||
|
|
||
|
@par Complexity
|
||
|
Linear in `this->buffer().size()`.
|
||
|
|
||
|
@return an iterator to the param
|
||
|
|
||
|
@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.
|
||
|
*/
|
||
|
iterator
|
||
|
find(
|
||
|
core::string_view key,
|
||
|
ignore_case_param ic = {}) const noexcept;
|
||
|
|
||
|
/** Find a matching key
|
||
|
|
||
|
This function examines the
|
||
|
parameters in the container to
|
||
|
find a match for the specified key.
|
||
|
The comparison is performed as if all
|
||
|
escaped characters were decoded first.
|
||
|
|
||
|
<br>
|
||
|
|
||
|
The search starts at `from`
|
||
|
and proceeds forward until either the
|
||
|
key is found or the end of the range is
|
||
|
reached, in which case `end()` is
|
||
|
returned.
|
||
|
|
||
|
@par Example
|
||
|
@code
|
||
|
url_view u( "?First=John&Last=Doe" );
|
||
|
|
||
|
assert( u.params().find( "first" ) != u.params().find( "first", ignore_case ) );
|
||
|
@endcode
|
||
|
|
||
|
@par Complexity
|
||
|
Linear in `this->buffer().size()`.
|
||
|
|
||
|
@return an iterator to the param
|
||
|
|
||
|
@param from The position to begin the
|
||
|
search from. This can be `end()`.
|
||
|
|
||
|
@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.
|
||
|
*/
|
||
|
iterator
|
||
|
find(
|
||
|
iterator from,
|
||
|
core::string_view key,
|
||
|
ignore_case_param ic = {}) const noexcept;
|
||
|
|
||
|
/** Find a matching key
|
||
|
|
||
|
This function examines the
|
||
|
parameters in the container to
|
||
|
find a match for the specified key.
|
||
|
The comparison is performed as if all
|
||
|
escaped characters were decoded first.
|
||
|
|
||
|
<br>
|
||
|
|
||
|
The search starts from the last param
|
||
|
and proceeds backwards until either the
|
||
|
key is found or the beginning of the
|
||
|
range is reached, in which case `end()`
|
||
|
is returned.
|
||
|
|
||
|
@par Example
|
||
|
@code
|
||
|
assert( (*url_view( "?first=John&last=Doe" ).params().find_last( "last" )).value == "Doe" );
|
||
|
@endcode
|
||
|
|
||
|
@par Complexity
|
||
|
Linear in `this->buffer().size()`.
|
||
|
|
||
|
@return an iterator to the param
|
||
|
|
||
|
@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.
|
||
|
*/
|
||
|
iterator
|
||
|
find_last(
|
||
|
core::string_view key,
|
||
|
ignore_case_param ic = {}) const noexcept;
|
||
|
|
||
|
/** Find a matching key
|
||
|
|
||
|
This function examines the
|
||
|
parameters in the container to
|
||
|
find a match for the specified key.
|
||
|
The comparison is performed as if all
|
||
|
escaped characters were decoded first.
|
||
|
|
||
|
<br>
|
||
|
|
||
|
The search starts prior to `before`
|
||
|
and proceeds backwards until either the
|
||
|
key is found or the beginning of the
|
||
|
range is reached, in which case `end()`
|
||
|
is returned.
|
||
|
|
||
|
@par Example
|
||
|
@code
|
||
|
url_view u( "?First=John&Last=Doe" );
|
||
|
|
||
|
assert( u.params().find_last( "last" ) != u.params().find_last( "last", ignore_case ) );
|
||
|
@endcode
|
||
|
|
||
|
@par Complexity
|
||
|
Linear in `this->buffer().size()`.
|
||
|
|
||
|
@return an iterator to the param
|
||
|
|
||
|
@param before One past the position
|
||
|
to begin the search from. This can
|
||
|
be `end()`.
|
||
|
|
||
|
@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.
|
||
|
*/
|
||
|
iterator
|
||
|
find_last(
|
||
|
iterator before,
|
||
|
core::string_view key,
|
||
|
ignore_case_param ic = {}) const noexcept;
|
||
|
|
||
|
private:
|
||
|
detail::params_iter_impl
|
||
|
find_impl(
|
||
|
detail::params_iter_impl,
|
||
|
core::string_view,
|
||
|
ignore_case_param) const noexcept;
|
||
|
|
||
|
detail::params_iter_impl
|
||
|
find_last_impl(
|
||
|
detail::params_iter_impl,
|
||
|
core::string_view,
|
||
|
ignore_case_param) const noexcept;
|
||
|
};
|
||
|
|
||
|
//------------------------------------------------
|
||
|
|
||
|
/** Format to an output stream
|
||
|
|
||
|
Any percent-escapes are emitted as-is;
|
||
|
no decoding is performed.
|
||
|
|
||
|
@par Complexity
|
||
|
Linear in `ps.buffer().size()`.
|
||
|
|
||
|
@par Effects
|
||
|
@code
|
||
|
return os << ps.buffer();
|
||
|
@endcode
|
||
|
*/
|
||
|
BOOST_URL_DECL
|
||
|
std::ostream&
|
||
|
operator<<(
|
||
|
std::ostream& os,
|
||
|
params_base const& qp);
|
||
|
|
||
|
} // urls
|
||
|
} // boost
|
||
|
|
||
|
#include <boost/url/impl/params_base.hpp>
|
||
|
|
||
|
#endif
|