mirror of
https://github.com/vdemydiuk/mtapi.git
synced 2026-08-06 15:37:52 +00:00
Added thirdparty: boost library
This commit is contained in:
+1441
File diff suppressed because it is too large
Load Diff
+697
@@ -0,0 +1,697 @@
|
||||
//
|
||||
// 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_DECODE_VIEW_HPP
|
||||
#define BOOST_URL_DECODE_VIEW_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/url/encoding_opts.hpp>
|
||||
#include <boost/url/pct_string_view.hpp>
|
||||
#include <type_traits>
|
||||
#include <iterator>
|
||||
#include <iosfwd>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
class decode_view;
|
||||
|
||||
namespace detail {
|
||||
|
||||
// unchecked
|
||||
template<class... Args>
|
||||
decode_view
|
||||
make_decode_view(
|
||||
Args&&... args) noexcept;
|
||||
|
||||
} // detail
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** A reference to a valid, percent-encoded string
|
||||
|
||||
These views reference strings in parts of URLs
|
||||
or other components that are percent-encoded.
|
||||
The special characters (those not in the
|
||||
allowed character set) are stored as three
|
||||
character escapes that consist of a percent
|
||||
sign ('%%') followed by a two-digit hexadecimal
|
||||
number of the corresponding unescaped character
|
||||
code, which may be part of a UTF-8 code point
|
||||
depending on the context.
|
||||
|
||||
The view refers to the original character
|
||||
buffer and only decodes escaped sequences when
|
||||
needed. In particular these operations perform
|
||||
percent-decoding automatically without the
|
||||
need to allocate memory:
|
||||
|
||||
@li Iteration of the string
|
||||
@li Accessing the encoded character buffer
|
||||
@li Comparison to encoded or plain strings
|
||||
|
||||
These objects can only be constructed from
|
||||
strings that have a valid percent-encoding,
|
||||
otherwise construction fails. The caller is
|
||||
responsible for ensuring that the lifetime
|
||||
of the character buffer from which the view
|
||||
is constructed extends unmodified until the
|
||||
view is no longer accessed.
|
||||
|
||||
@par Operators
|
||||
The following operators are supported between
|
||||
@ref decode_view and any object that is convertible
|
||||
to `core::string_view`
|
||||
|
||||
@code
|
||||
bool operator==( decode_view, decode_view ) noexcept;
|
||||
bool operator!=( decode_view, decode_view ) noexcept;
|
||||
bool operator<=( decode_view, decode_view ) noexcept;
|
||||
bool operator< ( decode_view, decode_view ) noexcept;
|
||||
bool operator> ( decode_view, decode_view ) noexcept;
|
||||
bool operator>=( decode_view, decode_view ) noexcept;
|
||||
@endcode
|
||||
|
||||
*/
|
||||
class decode_view
|
||||
{
|
||||
char const* p_ = nullptr;
|
||||
std::size_t n_ = 0;
|
||||
std::size_t dn_ = 0;
|
||||
bool space_as_plus_ = true;
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
template<class... Args>
|
||||
friend
|
||||
decode_view
|
||||
detail::make_decode_view(
|
||||
Args&&... args) noexcept;
|
||||
#endif
|
||||
|
||||
// unchecked
|
||||
BOOST_URL_DECL
|
||||
explicit
|
||||
decode_view(
|
||||
core::string_view s,
|
||||
std::size_t n,
|
||||
encoding_opts opt) noexcept;
|
||||
|
||||
public:
|
||||
/** The value type
|
||||
*/
|
||||
using value_type = char;
|
||||
|
||||
/** The reference type
|
||||
*/
|
||||
using reference = char;
|
||||
|
||||
/// @copydoc reference
|
||||
using const_reference = char;
|
||||
|
||||
/** The unsigned integer type
|
||||
*/
|
||||
using size_type = std::size_t;
|
||||
|
||||
/** The signed integer type
|
||||
*/
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
/** An iterator of constant, decoded characters.
|
||||
|
||||
This iterator is used to access the encoded
|
||||
string as a bidirectional range of characters
|
||||
with percent-decoding applied. Escape sequences
|
||||
are not decoded until the iterator is
|
||||
dereferenced.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
using iterator = __see_below__;
|
||||
#else
|
||||
class iterator;
|
||||
#endif
|
||||
|
||||
/// @copydoc iterator
|
||||
using const_iterator = iterator;
|
||||
|
||||
//--------------------------------------------
|
||||
//
|
||||
// Special Members
|
||||
//
|
||||
//--------------------------------------------
|
||||
|
||||
/** Constructor
|
||||
|
||||
Default-constructed views represent
|
||||
empty strings.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
decode_view ds;
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->empty() == true
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
decode_view() noexcept = default;
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs a view from the character
|
||||
buffer `s`, which must remain valid and
|
||||
unmodified until the view is no longer
|
||||
accessed.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
decode_view ds( "Program%20Files" );
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->encoded() == s
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `s.size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@throw system_error
|
||||
The string contains an invalid percent encoding.
|
||||
|
||||
@param s A percent-encoded string that has
|
||||
already been validated.
|
||||
|
||||
@param opt The options for decoding. If
|
||||
this parameter is omitted, the default
|
||||
options are used.
|
||||
*/
|
||||
explicit
|
||||
decode_view(
|
||||
pct_string_view s,
|
||||
encoding_opts opt = {}) noexcept
|
||||
: decode_view(
|
||||
detail::to_sv(s),
|
||||
s.decoded_size(),
|
||||
opt)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
//
|
||||
// Observers
|
||||
//
|
||||
//--------------------------------------------
|
||||
|
||||
/** Return true if the string is empty
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( decode_view( "" ).empty() );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
bool
|
||||
empty() const noexcept
|
||||
{
|
||||
return n_ == 0;
|
||||
}
|
||||
|
||||
/** Return the number of decoded characters
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( decode_view( "Program%20Files" ).size() == 13 );
|
||||
@endcode
|
||||
|
||||
@par Effects
|
||||
@code
|
||||
return std::distance( this->begin(), this->end() );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
size_type
|
||||
size() const noexcept
|
||||
{
|
||||
return dn_;
|
||||
}
|
||||
|
||||
/** Return an iterator to the beginning
|
||||
|
||||
@par Example
|
||||
@code
|
||||
auto it = this->begin();
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
iterator
|
||||
begin() const noexcept;
|
||||
|
||||
/** Return an iterator to the end
|
||||
|
||||
@par Example
|
||||
@code
|
||||
auto it = this->end();
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
iterator
|
||||
end() const noexcept;
|
||||
|
||||
/** Return the first character
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( decode_view( "Program%20Files" ).front() == 'P' );
|
||||
@endcode
|
||||
|
||||
@par Preconditions
|
||||
@code
|
||||
not this->empty()
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
reference
|
||||
front() const noexcept;
|
||||
|
||||
/** Return the last character
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( decode_view( "Program%20Files" ).back() == 's' );
|
||||
@endcode
|
||||
|
||||
@par Preconditions
|
||||
@code
|
||||
not this->empty()
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
reference
|
||||
back() const noexcept;
|
||||
|
||||
/** Checks if the string begins with the given prefix
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( decode_view( "Program%20Files" ).starts_with("Program") );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
bool
|
||||
starts_with( core::string_view s ) const noexcept;
|
||||
|
||||
/** Checks if the string ends with the given prefix
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( decode_view( "Program%20Files" ).ends_with("Files") );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
bool
|
||||
ends_with( core::string_view s ) const noexcept;
|
||||
|
||||
/** Checks if the string begins with the given prefix
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( decode_view( "Program%20Files" ).starts_with('P') );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
bool
|
||||
starts_with( char ch ) const noexcept;
|
||||
|
||||
/** Checks if the string ends with the given prefix
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( decode_view( "Program%20Files" ).ends_with('s') );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
bool
|
||||
ends_with( char ch ) const noexcept;
|
||||
|
||||
/** Finds the first occurrence of character in this view
|
||||
|
||||
@par Complexity
|
||||
Linear.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
const_iterator
|
||||
find( char ch ) const noexcept;
|
||||
|
||||
/** Finds the first occurrence of character in this view
|
||||
|
||||
@par Complexity
|
||||
Linear.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
const_iterator
|
||||
rfind( char ch ) const noexcept;
|
||||
|
||||
/** Remove the first characters
|
||||
|
||||
@par Example
|
||||
@code
|
||||
decode_view d( "Program%20Files" );
|
||||
d.remove_prefix( 8 );
|
||||
assert( d == "Files" );
|
||||
@endcode
|
||||
|
||||
@par Preconditions
|
||||
@code
|
||||
not this->empty()
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
void
|
||||
remove_prefix( size_type n );
|
||||
|
||||
/** Remove the last characters
|
||||
|
||||
@par Example
|
||||
@code
|
||||
decode_view d( "Program%20Files" );
|
||||
d.remove_prefix( 6 );
|
||||
assert( d == "Program" );
|
||||
@endcode
|
||||
|
||||
@par Preconditions
|
||||
@code
|
||||
not this->empty()
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
void
|
||||
remove_suffix( size_type n );
|
||||
|
||||
/** Return the decoding options
|
||||
*/
|
||||
encoding_opts
|
||||
options() const noexcept
|
||||
{
|
||||
encoding_opts opt;
|
||||
opt.space_as_plus = space_as_plus_;
|
||||
return opt;
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
//
|
||||
// Comparison
|
||||
//
|
||||
//--------------------------------------------
|
||||
|
||||
/** Return the result of comparing to another string
|
||||
|
||||
The length of the sequences to compare is the smaller of
|
||||
`size()` and `other.size()`.
|
||||
|
||||
The function compares the two strings as if by calling
|
||||
`char_traits<char>::compare(to_string().data(), v.data(), rlen)`.
|
||||
This means the comparison is performed with
|
||||
percent-decoding applied to the current string.
|
||||
|
||||
@param other string to compare
|
||||
|
||||
@return Negative value if this string is less than the other
|
||||
character sequence, zero if the both character sequences are
|
||||
equal, positive value if this string is greater than the other
|
||||
character sequence
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
int
|
||||
compare(core::string_view other) const noexcept;
|
||||
|
||||
/** Return the result of comparing to another string
|
||||
|
||||
The length of the sequences to compare is the smaller of
|
||||
`size()` and `other.size()`.
|
||||
|
||||
The function compares the two strings as if by calling
|
||||
`char_traits<char>::compare(to_string().data(), v.to_string().data(), rlen)`.
|
||||
This means the comparison is performed with
|
||||
percent-decoding applied to the current string.
|
||||
|
||||
@param other string to compare
|
||||
|
||||
@return Negative value if this string is less than the other
|
||||
character sequence, zero if the both character sequences are
|
||||
equal, positive value if this string is greater than the other
|
||||
character sequence
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
int
|
||||
compare(decode_view other) const noexcept;
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
// relational operators
|
||||
#ifndef BOOST_URL_DOCS
|
||||
private:
|
||||
template<class S0, class S1>
|
||||
using is_match = std::integral_constant<bool,
|
||||
// both decode_view or convertible to core::string_view
|
||||
(
|
||||
std::is_same<typename std::decay<S0>::type, decode_view>::value ||
|
||||
std::is_convertible<S0, core::string_view>::value) &&
|
||||
(
|
||||
std::is_same<typename std::decay<S1>::type, decode_view>::value ||
|
||||
std::is_convertible<S1, core::string_view>::value) &&
|
||||
// not both are convertible to string view
|
||||
(
|
||||
!std::is_convertible<S0, core::string_view>::value ||
|
||||
!std::is_convertible<S1, core::string_view>::value)>;
|
||||
|
||||
static
|
||||
int
|
||||
decode_compare(decode_view s0, decode_view s1) noexcept
|
||||
{
|
||||
return s0.compare(s1);
|
||||
}
|
||||
|
||||
template <class S>
|
||||
static
|
||||
int
|
||||
decode_compare(decode_view s0, S const& s1) noexcept
|
||||
{
|
||||
return s0.compare(s1);
|
||||
}
|
||||
|
||||
template <class S>
|
||||
static
|
||||
int
|
||||
decode_compare(S const& s0, decode_view s1) noexcept
|
||||
{
|
||||
return -s1.compare(s0);
|
||||
}
|
||||
public:
|
||||
|
||||
template<class S0, class S1>
|
||||
BOOST_CXX14_CONSTEXPR friend auto operator==(
|
||||
S0 const& s0, S1 const& s1) noexcept ->
|
||||
typename std::enable_if<
|
||||
is_match<S0, S1>::value, bool>::type
|
||||
{
|
||||
return decode_compare(s0, s1) == 0;
|
||||
}
|
||||
|
||||
template<class S0, class S1>
|
||||
BOOST_CXX14_CONSTEXPR friend auto operator!=(
|
||||
S0 const& s0, S1 const& s1) noexcept ->
|
||||
typename std::enable_if<
|
||||
is_match<S0, S1>::value, bool>::type
|
||||
{
|
||||
return decode_compare(s0, s1) != 0;
|
||||
}
|
||||
|
||||
template<class S0, class S1>
|
||||
BOOST_CXX14_CONSTEXPR friend auto operator<(
|
||||
S0 const& s0, S1 const& s1) noexcept ->
|
||||
typename std::enable_if<
|
||||
is_match<S0, S1>::value, bool>::type
|
||||
{
|
||||
return decode_compare(s0, s1) < 0;
|
||||
}
|
||||
|
||||
template<class S0, class S1>
|
||||
BOOST_CXX14_CONSTEXPR friend auto operator<=(
|
||||
S0 const& s0, S1 const& s1) noexcept ->
|
||||
typename std::enable_if<
|
||||
is_match<S0, S1>::value, bool>::type
|
||||
{
|
||||
return decode_compare(s0, s1) <= 0;
|
||||
}
|
||||
|
||||
template<class S0, class S1>
|
||||
BOOST_CXX14_CONSTEXPR friend auto operator>(
|
||||
S0 const& s0, S1 const& s1) noexcept ->
|
||||
typename std::enable_if<
|
||||
is_match<S0, S1>::value, bool>::type
|
||||
{
|
||||
return decode_compare(s0, s1) > 0;
|
||||
}
|
||||
|
||||
template<class S0, class S1>
|
||||
BOOST_CXX14_CONSTEXPR friend auto operator>=(
|
||||
S0 const& s0, S1 const& s1) noexcept ->
|
||||
typename std::enable_if<
|
||||
is_match<S0, S1>::value, bool>::type
|
||||
{
|
||||
return decode_compare(s0, s1) >= 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// hidden friend
|
||||
friend
|
||||
std::ostream&
|
||||
operator<<(
|
||||
std::ostream& os,
|
||||
decode_view const& s)
|
||||
{
|
||||
// hidden friend
|
||||
s.write(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
BOOST_URL_DECL
|
||||
void
|
||||
write(std::ostream& os) const;
|
||||
};
|
||||
|
||||
/** Format the string with percent-decoding applied to the output stream
|
||||
|
||||
This function serializes the decoded view
|
||||
to the output stream.
|
||||
|
||||
@return A reference to the output stream, for chaining
|
||||
|
||||
@param os The output stream to write to
|
||||
|
||||
@param s The decoded view to write
|
||||
*/
|
||||
inline
|
||||
std::ostream&
|
||||
operator<<(
|
||||
std::ostream& os,
|
||||
decode_view const& s);
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
inline
|
||||
decode_view
|
||||
pct_string_view::operator*() const noexcept
|
||||
{
|
||||
return decode_view(*this);
|
||||
}
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
namespace detail {
|
||||
template<class... Args>
|
||||
decode_view
|
||||
make_decode_view(
|
||||
Args&&... args) noexcept
|
||||
{
|
||||
return decode_view(
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
} // detail
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#include <boost/url/impl/decode_view.hpp>
|
||||
|
||||
#endif
|
||||
+426
@@ -0,0 +1,426 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_DETAIL_ANY_PARAMS_ITER_HPP
|
||||
#define BOOST_URL_DETAIL_ANY_PARAMS_ITER_HPP
|
||||
|
||||
#include <boost/url/param.hpp>
|
||||
#include <boost/url/pct_string_view.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// any_params_iter
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
/* An iterator to a type-erased,
|
||||
possibly encoded sequence of
|
||||
query params_ref.
|
||||
*/
|
||||
struct BOOST_SYMBOL_VISIBLE
|
||||
any_params_iter
|
||||
{
|
||||
protected:
|
||||
any_params_iter(
|
||||
bool empty_,
|
||||
core::string_view s0_ = {},
|
||||
core::string_view s1_ = {}) noexcept
|
||||
: s0(s0_)
|
||||
, s1(s1_)
|
||||
, empty(empty_)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
// these are adjusted
|
||||
// when self-intersecting
|
||||
core::string_view s0;
|
||||
core::string_view s1;
|
||||
|
||||
// True if the sequence is empty
|
||||
bool empty = false;
|
||||
|
||||
BOOST_URL_DECL
|
||||
virtual
|
||||
~any_params_iter() noexcept = 0;
|
||||
|
||||
// Rewind the iterator to the beginning
|
||||
virtual
|
||||
void
|
||||
rewind() noexcept = 0;
|
||||
|
||||
// Measure and increment current element
|
||||
// element.
|
||||
// Returns false on end of range.
|
||||
// n is increased by encoded size.
|
||||
// Can throw on bad percent-escape
|
||||
virtual
|
||||
bool
|
||||
measure(std::size_t& n) = 0;
|
||||
|
||||
// Copy and increment the current
|
||||
// element. encoding is performed
|
||||
// if needed.
|
||||
virtual
|
||||
void
|
||||
copy(
|
||||
char*& dest,
|
||||
char const* end) noexcept = 0;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// query_iter
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
// A string of plain query params
|
||||
struct BOOST_SYMBOL_VISIBLE
|
||||
query_iter
|
||||
: any_params_iter
|
||||
{
|
||||
// ne = never empty
|
||||
BOOST_URL_DECL
|
||||
explicit
|
||||
query_iter(
|
||||
core::string_view s,
|
||||
bool ne = false) noexcept;
|
||||
|
||||
private:
|
||||
core::string_view s_;
|
||||
std::size_t n_;
|
||||
char const* p_;
|
||||
bool at_end_;
|
||||
|
||||
void rewind() noexcept override;
|
||||
bool measure(std::size_t&) noexcept override;
|
||||
void copy(char*&, char const*) noexcept override;
|
||||
void increment() noexcept;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// param_iter
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
// A 1-param range allowing
|
||||
// self-intersection
|
||||
struct BOOST_SYMBOL_VISIBLE
|
||||
param_iter
|
||||
: any_params_iter
|
||||
{
|
||||
explicit
|
||||
param_iter(
|
||||
param_view const&) noexcept;
|
||||
|
||||
private:
|
||||
bool has_value_;
|
||||
bool at_end_ = false;
|
||||
|
||||
void rewind() noexcept override;
|
||||
bool measure(std::size_t&) noexcept override;
|
||||
void copy(char*&, char const*) noexcept override;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// params_iter_base
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
struct params_iter_base
|
||||
{
|
||||
protected:
|
||||
// return encoded size
|
||||
BOOST_URL_DECL
|
||||
static
|
||||
void
|
||||
measure_impl(
|
||||
std::size_t& n,
|
||||
param_view const& p) noexcept;
|
||||
|
||||
// encode to dest
|
||||
BOOST_URL_DECL
|
||||
static
|
||||
void
|
||||
copy_impl(
|
||||
char*& dest,
|
||||
char const* end,
|
||||
param_view const& v) noexcept;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
// A range of plain query params_ref
|
||||
template<class FwdIt>
|
||||
struct params_iter
|
||||
: any_params_iter
|
||||
, private params_iter_base
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
std::is_convertible<
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::reference,
|
||||
param_view>::value);
|
||||
|
||||
params_iter(
|
||||
FwdIt first,
|
||||
FwdIt last) noexcept
|
||||
: any_params_iter(
|
||||
first == last)
|
||||
, it0_(first)
|
||||
, it_(first)
|
||||
, end_(last)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
FwdIt it0_;
|
||||
FwdIt it_;
|
||||
FwdIt end_;
|
||||
|
||||
void
|
||||
rewind() noexcept override
|
||||
{
|
||||
it_ = it0_;
|
||||
}
|
||||
|
||||
bool
|
||||
measure(
|
||||
std::size_t& n) noexcept override
|
||||
{
|
||||
if(it_ == end_)
|
||||
return false;
|
||||
measure_impl(n,
|
||||
param_view(*it_++));
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
copy(
|
||||
char*& dest,
|
||||
char const* end) noexcept override
|
||||
{
|
||||
copy_impl(dest, end,
|
||||
param_view(*it_++));
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// param_encoded_iter
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
// A 1-param encoded range
|
||||
// allowing self-intersection
|
||||
struct BOOST_SYMBOL_VISIBLE
|
||||
param_encoded_iter
|
||||
: any_params_iter
|
||||
{
|
||||
explicit
|
||||
param_encoded_iter(
|
||||
param_pct_view const&) noexcept;
|
||||
|
||||
private:
|
||||
bool has_value_;
|
||||
bool at_end_ = false;
|
||||
|
||||
void rewind() noexcept override;
|
||||
bool measure(std::size_t&) noexcept override;
|
||||
void copy(char*&, char const*) noexcept override;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// params_encoded_iter
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
// Validating and copying from
|
||||
// a string of encoded params
|
||||
struct params_encoded_iter_base
|
||||
{
|
||||
protected:
|
||||
BOOST_URL_DECL
|
||||
static
|
||||
void
|
||||
measure_impl(
|
||||
std::size_t& n,
|
||||
param_view const& v) noexcept;
|
||||
|
||||
BOOST_URL_DECL
|
||||
static
|
||||
void
|
||||
copy_impl(
|
||||
char*& dest,
|
||||
char const* end,
|
||||
param_view const& v) noexcept;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
// A range of encoded query params_ref
|
||||
template<class FwdIt>
|
||||
struct params_encoded_iter
|
||||
: any_params_iter
|
||||
, private params_encoded_iter_base
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
std::is_convertible<
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::reference,
|
||||
param_view>::value);
|
||||
|
||||
params_encoded_iter(
|
||||
FwdIt first,
|
||||
FwdIt last) noexcept
|
||||
: any_params_iter(
|
||||
first == last)
|
||||
, it0_(first)
|
||||
, it_(first)
|
||||
, end_(last)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
FwdIt it0_;
|
||||
FwdIt it_;
|
||||
FwdIt end_;
|
||||
|
||||
void
|
||||
rewind() noexcept override
|
||||
{
|
||||
it_ = it0_;
|
||||
}
|
||||
|
||||
bool
|
||||
measure(
|
||||
std::size_t& n) override
|
||||
{
|
||||
if(it_ == end_)
|
||||
return false;
|
||||
// throw on invalid input
|
||||
measure_impl(n,
|
||||
param_pct_view(
|
||||
param_view(*it_++)));
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
copy(
|
||||
char*& dest,
|
||||
char const* end
|
||||
) noexcept override
|
||||
{
|
||||
copy_impl(dest, end,
|
||||
param_view(*it_++));
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// param_value_iter
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
// An iterator which outputs
|
||||
// one value on an existing key
|
||||
struct param_value_iter
|
||||
: any_params_iter
|
||||
{
|
||||
param_value_iter(
|
||||
std::size_t nk,
|
||||
core::string_view const& value,
|
||||
bool has_value) noexcept
|
||||
: any_params_iter(
|
||||
false,
|
||||
value)
|
||||
, nk_(nk)
|
||||
, has_value_(has_value)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t nk_ = 0;
|
||||
bool has_value_ = false;
|
||||
bool at_end_ = false;
|
||||
|
||||
void rewind() noexcept override;
|
||||
bool measure(std::size_t&) noexcept override;
|
||||
void copy(char*&, char const*) noexcept override;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// param_encoded_value_iter
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
// An iterator which outputs one
|
||||
// encoded value on an existing key
|
||||
struct param_encoded_value_iter
|
||||
: any_params_iter
|
||||
{
|
||||
param_encoded_value_iter(
|
||||
std::size_t nk,
|
||||
pct_string_view const& value,
|
||||
bool has_value) noexcept
|
||||
: any_params_iter(
|
||||
false,
|
||||
value)
|
||||
, nk_(nk)
|
||||
, has_value_(has_value)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t nk_ = 0;
|
||||
bool has_value_ = false;
|
||||
bool at_end_ = false;
|
||||
|
||||
void rewind() noexcept override;
|
||||
bool measure(std::size_t&) noexcept override;
|
||||
void copy(char*&, char const*) noexcept override;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<class FwdIt>
|
||||
params_iter<FwdIt>
|
||||
make_params_iter(
|
||||
FwdIt first, FwdIt last)
|
||||
{
|
||||
return params_iter<
|
||||
FwdIt>(first, last);
|
||||
}
|
||||
|
||||
template<class FwdIt>
|
||||
params_encoded_iter<FwdIt>
|
||||
make_params_encoded_iter(
|
||||
FwdIt first, FwdIt last)
|
||||
{
|
||||
return params_encoded_iter<
|
||||
FwdIt>(first, last);
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+327
@@ -0,0 +1,327 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_DETAIL_ANY_SEGMENTS_ITER_HPP
|
||||
#define BOOST_URL_DETAIL_ANY_SEGMENTS_ITER_HPP
|
||||
|
||||
#include <boost/url/pct_string_view.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
struct BOOST_SYMBOL_VISIBLE
|
||||
any_segments_iter
|
||||
{
|
||||
protected:
|
||||
explicit
|
||||
any_segments_iter(
|
||||
core::string_view s_ = {}) noexcept
|
||||
: s(s_)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~any_segments_iter() = default;
|
||||
|
||||
public:
|
||||
// this is adjusted
|
||||
// when self-intersecting
|
||||
core::string_view s;
|
||||
|
||||
// the first segment,
|
||||
// to handle special cases
|
||||
core::string_view front;
|
||||
|
||||
// quick number of segments
|
||||
// 0 = zero
|
||||
// 1 = one
|
||||
// 2 = two, or more
|
||||
int fast_nseg = 0;
|
||||
|
||||
// whether the segments should encode colons
|
||||
// when we measure and copy. the calling
|
||||
// function uses this for the first
|
||||
// segment in some cases, such as:
|
||||
// "x:y:z" -> remove_scheme -> "y%3Az"
|
||||
// as "y:z" would no longer represent a path
|
||||
bool encode_colons = false;
|
||||
|
||||
// Rewind the iterator to the beginning
|
||||
virtual void rewind() noexcept = 0;
|
||||
|
||||
// Measure and increment the current
|
||||
// element. n is increased by the
|
||||
// encoded size. Returns false on
|
||||
// end of range.
|
||||
virtual bool measure(std::size_t& n) = 0;
|
||||
|
||||
// Copy and increment the current
|
||||
// element, encoding as needed.
|
||||
virtual void copy(char*& dest,
|
||||
char const* end) noexcept = 0;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// segment_iter
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
// A 1-segment range
|
||||
// allowing self-intersection
|
||||
struct BOOST_SYMBOL_VISIBLE
|
||||
segment_iter
|
||||
: any_segments_iter
|
||||
{
|
||||
virtual ~segment_iter() = default;
|
||||
|
||||
explicit
|
||||
segment_iter(
|
||||
core::string_view s) noexcept;
|
||||
|
||||
private:
|
||||
bool at_end_ = false;
|
||||
void rewind() noexcept override;
|
||||
bool measure(std::size_t&) noexcept override;
|
||||
void copy(char*&, char const*) noexcept override;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// segments_iter
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
struct segments_iter_base
|
||||
{
|
||||
protected:
|
||||
BOOST_URL_DECL static void
|
||||
measure_impl(std::size_t&,
|
||||
core::string_view, bool) noexcept;
|
||||
BOOST_URL_DECL static void
|
||||
copy_impl(char*&, char const*,
|
||||
core::string_view, bool) noexcept;
|
||||
};
|
||||
|
||||
// iterates segments in a
|
||||
// plain segment range
|
||||
template<class FwdIt>
|
||||
struct segments_iter
|
||||
: any_segments_iter
|
||||
, segments_iter_base
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
std::is_convertible<
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::reference,
|
||||
core::string_view>::value);
|
||||
|
||||
segments_iter(
|
||||
FwdIt first,
|
||||
FwdIt last) noexcept
|
||||
: it_(first)
|
||||
, it0_(first)
|
||||
, end_(last)
|
||||
{
|
||||
if(first != last)
|
||||
{
|
||||
front = *first;
|
||||
auto it = first;
|
||||
if(++it == last)
|
||||
fast_nseg = 1;
|
||||
else
|
||||
fast_nseg = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
fast_nseg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
FwdIt it_;
|
||||
FwdIt it0_;
|
||||
FwdIt end_;
|
||||
|
||||
void
|
||||
rewind() noexcept override
|
||||
{
|
||||
it_ = it0_;
|
||||
}
|
||||
|
||||
bool
|
||||
measure(
|
||||
std::size_t& n) noexcept override
|
||||
{
|
||||
if(it_ == end_)
|
||||
return false;
|
||||
measure_impl(n,
|
||||
detail::to_sv(*it_),
|
||||
encode_colons);
|
||||
++it_;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
copy(
|
||||
char*& dest,
|
||||
char const* end) noexcept override
|
||||
{
|
||||
copy_impl(dest, end,
|
||||
detail::to_sv(*it_++),
|
||||
encode_colons);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// segment_encoded_iter
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
// A 1-segment range
|
||||
// allowing self-intersection
|
||||
struct BOOST_SYMBOL_VISIBLE
|
||||
segment_encoded_iter
|
||||
: any_segments_iter
|
||||
{
|
||||
virtual ~segment_encoded_iter() = default;
|
||||
|
||||
explicit
|
||||
segment_encoded_iter(
|
||||
pct_string_view const& s) noexcept;
|
||||
|
||||
private:
|
||||
bool at_end_ = false;
|
||||
void rewind() noexcept override;
|
||||
bool measure(std::size_t&) noexcept override;
|
||||
void copy(char*&, char const*) noexcept override;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// segments_encoded_iter
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
// Validating and copying from
|
||||
// a string of encoded segments
|
||||
struct segments_encoded_iter_base
|
||||
{
|
||||
protected:
|
||||
BOOST_URL_DECL static void
|
||||
measure_impl(std::size_t&,
|
||||
core::string_view, bool) noexcept;
|
||||
BOOST_URL_DECL static void
|
||||
copy_impl(char*&, char const*,
|
||||
core::string_view, bool) noexcept;
|
||||
};
|
||||
|
||||
// iterates segments in an
|
||||
// encoded segment range
|
||||
template<class FwdIt>
|
||||
struct segments_encoded_iter
|
||||
: public any_segments_iter
|
||||
, public segments_encoded_iter_base
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
std::is_convertible<
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::reference,
|
||||
core::string_view>::value);
|
||||
|
||||
segments_encoded_iter(
|
||||
FwdIt first,
|
||||
FwdIt last)
|
||||
: it_(first)
|
||||
, it0_(first)
|
||||
, end_(last)
|
||||
{
|
||||
if(it_ != end_)
|
||||
{
|
||||
// throw on invalid input
|
||||
front = pct_string_view(
|
||||
detail::to_sv(*first));
|
||||
auto it = first;
|
||||
if(++it == last)
|
||||
fast_nseg = 1;
|
||||
else
|
||||
fast_nseg = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
fast_nseg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
FwdIt it_;
|
||||
FwdIt it0_;
|
||||
FwdIt end_;
|
||||
|
||||
void
|
||||
rewind() noexcept override
|
||||
{
|
||||
it_ = it0_;
|
||||
}
|
||||
|
||||
bool
|
||||
measure(
|
||||
std::size_t& n) override
|
||||
{
|
||||
if(it_ == end_)
|
||||
return false;
|
||||
// throw on invalid input
|
||||
measure_impl(n,
|
||||
pct_string_view(
|
||||
detail::to_sv(*it_++)),
|
||||
encode_colons);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
copy(
|
||||
char*& dest,
|
||||
char const* end) noexcept override
|
||||
{
|
||||
copy_impl(dest, end,
|
||||
detail::to_sv(*it_++),
|
||||
encode_colons);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<class FwdIt>
|
||||
segments_iter<FwdIt>
|
||||
make_segments_iter(
|
||||
FwdIt first, FwdIt last)
|
||||
{
|
||||
return segments_iter<
|
||||
FwdIt>(first, last);
|
||||
}
|
||||
|
||||
template<class FwdIt>
|
||||
segments_encoded_iter<FwdIt>
|
||||
make_segments_encoded_iter(
|
||||
FwdIt first, FwdIt last)
|
||||
{
|
||||
return segments_encoded_iter<
|
||||
FwdIt>(first, last);
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
//
|
||||
// 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_DETAIL_CONFIG_HPP
|
||||
#define BOOST_URL_DETAIL_CONFIG_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if CHAR_BIT != 8
|
||||
# error unsupported platform
|
||||
#endif
|
||||
|
||||
// Determine if compiling as a dynamic library
|
||||
#if (defined(BOOST_URL_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)) && !defined(BOOST_URL_STATIC_LINK)
|
||||
# define BOOST_URL_BUILD_DLL
|
||||
#endif
|
||||
|
||||
// Set visibility flags
|
||||
#if !defined(BOOST_URL_BUILD_DLL)
|
||||
# define BOOST_URL_DECL /* static library */
|
||||
#elif defined(BOOST_URL_SOURCE)
|
||||
# define BOOST_URL_DECL BOOST_SYMBOL_EXPORT /* source: dllexport/visibility */
|
||||
#else
|
||||
# define BOOST_URL_DECL BOOST_SYMBOL_IMPORT /* header: dllimport */
|
||||
#endif
|
||||
|
||||
// Set up auto-linker
|
||||
# if !defined(BOOST_URL_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_URL_NO_LIB)
|
||||
# define BOOST_LIB_NAME boost_url
|
||||
# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_URL_DYN_LINK)
|
||||
# define BOOST_DYN_LINK
|
||||
# endif
|
||||
# include <boost/config/auto_link.hpp>
|
||||
# endif
|
||||
|
||||
// Set up SSE2
|
||||
#if ! defined(BOOST_URL_NO_SSE2) && \
|
||||
! defined(BOOST_URL_USE_SSE2)
|
||||
# if (defined(_M_IX86) && _M_IX86_FP == 2) || \
|
||||
defined(_M_X64) || defined(__SSE2__)
|
||||
# define BOOST_URL_USE_SSE2
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// constexpr
|
||||
#if BOOST_WORKAROUND( BOOST_GCC_VERSION, <= 72000 ) || \
|
||||
BOOST_WORKAROUND( BOOST_CLANG_VERSION, <= 35000 )
|
||||
# define BOOST_URL_CONSTEXPR
|
||||
#else
|
||||
# define BOOST_URL_CONSTEXPR constexpr
|
||||
#endif
|
||||
|
||||
// Add source location to error codes
|
||||
#ifdef BOOST_URL_NO_SOURCE_LOCATION
|
||||
# define BOOST_URL_ERR(ev) (::boost::system::error_code(ev))
|
||||
# define BOOST_URL_RETURN_EC(ev) return (ev)
|
||||
# define BOOST_URL_POS ::boost::source_location()
|
||||
#else
|
||||
# define BOOST_URL_ERR(ev) (::boost::system::error_code( (ev), [] { \
|
||||
static constexpr auto loc((BOOST_CURRENT_LOCATION)); \
|
||||
return &loc; }()))
|
||||
# define BOOST_URL_RETURN_EC(ev) \
|
||||
static constexpr auto loc ## __LINE__((BOOST_CURRENT_LOCATION)); \
|
||||
return ::boost::system::error_code((ev), &loc ## __LINE__)
|
||||
# define BOOST_URL_POS (BOOST_CURRENT_LOCATION)
|
||||
#endif
|
||||
|
||||
// String token parameters
|
||||
#ifndef BOOST_URL_STRTOK_TPARAM
|
||||
#define BOOST_URL_STRTOK_TPARAM class StringToken = string_token::return_string
|
||||
#endif
|
||||
#ifndef BOOST_URL_STRTOK_RETURN
|
||||
#define BOOST_URL_STRTOK_RETURN typename StringToken::result_type
|
||||
#endif
|
||||
#ifndef BOOST_URL_STRTOK_ARG
|
||||
#define BOOST_URL_STRTOK_ARG(name) StringToken&& token = {}
|
||||
#endif
|
||||
|
||||
// Move
|
||||
#if BOOST_WORKAROUND( BOOST_GCC_VERSION, < 80000 ) || \
|
||||
BOOST_WORKAROUND( BOOST_CLANG_VERSION, < 30900 )
|
||||
#define BOOST_URL_RETURN(x) return std::move((x))
|
||||
#else
|
||||
#define BOOST_URL_RETURN(x) return (x)
|
||||
#endif
|
||||
|
||||
// Limit tests
|
||||
#ifndef BOOST_URL_MAX_SIZE
|
||||
// we leave room for a null,
|
||||
// and still fit in size_t
|
||||
#define BOOST_URL_MAX_SIZE ((std::size_t(-1))-1)
|
||||
#endif
|
||||
|
||||
// noinline attribute
|
||||
#ifdef BOOST_GCC
|
||||
#define BOOST_URL_NO_INLINE [[gnu::noinline]]
|
||||
#else
|
||||
#define BOOST_URL_NO_INLINE
|
||||
#endif
|
||||
|
||||
// libstdcxx copy-on-write strings
|
||||
#ifndef BOOST_URL_COW_STRINGS
|
||||
#if defined(BOOST_LIBSTDCXX_VERSION) && (BOOST_LIBSTDCXX_VERSION < 60000 || (defined(_GLIBCXX_USE_CXX11_ABI) && _GLIBCXX_USE_CXX11_ABI == 0))
|
||||
#define BOOST_URL_COW_STRINGS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// detect 32/64 bit
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
# define BOOST_URL_ARCH 64
|
||||
#elif UINTPTR_MAX == UINT32_MAX
|
||||
# define BOOST_URL_ARCH 32
|
||||
#else
|
||||
# error Unknown or unsupported architecture, please open an issue
|
||||
#endif
|
||||
|
||||
// deprecated attribute
|
||||
#if defined(BOOST_MSVC) || defined(BOOST_URL_DOCS)
|
||||
#define BOOST_URL_DEPRECATED(msg)
|
||||
#else
|
||||
#define BOOST_URL_DEPRECATED(msg) BOOST_DEPRECATED(msg)
|
||||
#endif
|
||||
|
||||
// avoid Boost.TypeTraits for these traits
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
template<class...> struct make_void { typedef void type; };
|
||||
template<class... Ts> using void_t = typename make_void<Ts...>::type;
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// 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_DETAIL_DECODE_HPP
|
||||
#define BOOST_URL_DETAIL_DECODE_HPP
|
||||
|
||||
#include <boost/url/encoding_opts.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
BOOST_URL_DECL
|
||||
char
|
||||
decode_one(
|
||||
char const* it) noexcept;
|
||||
|
||||
BOOST_URL_DECL
|
||||
std::size_t
|
||||
decode_bytes_unsafe(
|
||||
core::string_view s) noexcept;
|
||||
|
||||
BOOST_URL_DECL
|
||||
std::size_t
|
||||
decode_unsafe(
|
||||
char* dest,
|
||||
char const* end,
|
||||
core::string_view s,
|
||||
encoding_opts opt = {}) noexcept;
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+205
@@ -0,0 +1,205 @@
|
||||
//
|
||||
// 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_DETAIL_ENCODE_HPP
|
||||
#define BOOST_URL_DETAIL_ENCODE_HPP
|
||||
|
||||
#include <boost/url/encoding_opts.hpp>
|
||||
#include <boost/url/pct_string_view.hpp>
|
||||
#include <boost/url/grammar/hexdig_chars.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
constexpr
|
||||
char const* const hexdigs[] = {
|
||||
"0123456789ABCDEF",
|
||||
"0123456789abcdef" };
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
// re-encode is to percent-encode a
|
||||
// string that can already contain
|
||||
// escapes. Characters not in the
|
||||
// unreserved set are escaped, and
|
||||
// escapes are passed through unchanged.
|
||||
//
|
||||
template<class CharSet>
|
||||
std::size_t
|
||||
re_encoded_size_unsafe(
|
||||
core::string_view s,
|
||||
CharSet const& unreserved,
|
||||
encoding_opts opt) noexcept
|
||||
{
|
||||
std::size_t n = 0;
|
||||
auto const end = s.end();
|
||||
auto it = s.begin();
|
||||
if(opt.space_as_plus)
|
||||
{
|
||||
while(it != end)
|
||||
{
|
||||
if(*it != '%')
|
||||
{
|
||||
if( unreserved(*it)
|
||||
|| *it == ' ')
|
||||
n += 1;
|
||||
else
|
||||
n += 3;
|
||||
++it;
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(end - it >= 3);
|
||||
BOOST_ASSERT(
|
||||
grammar::hexdig_value(
|
||||
it[1]) >= 0);
|
||||
BOOST_ASSERT(
|
||||
grammar::hexdig_value(
|
||||
it[2]) >= 0);
|
||||
n += 3;
|
||||
it += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while(it != end)
|
||||
{
|
||||
if(*it != '%')
|
||||
{
|
||||
if(unreserved(*it))
|
||||
n += 1;
|
||||
else
|
||||
n += 3;
|
||||
++it;
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(end - it >= 3);
|
||||
BOOST_ASSERT(
|
||||
grammar::hexdig_value(
|
||||
it[1]) >= 0);
|
||||
BOOST_ASSERT(
|
||||
grammar::hexdig_value(
|
||||
it[2]) >= 0);
|
||||
n += 3;
|
||||
it += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
// unchecked
|
||||
// returns decoded size
|
||||
template<class CharSet>
|
||||
std::size_t
|
||||
re_encode_unsafe(
|
||||
char*& dest_,
|
||||
char const* const end,
|
||||
core::string_view s,
|
||||
CharSet const& unreserved,
|
||||
encoding_opts opt) noexcept
|
||||
{
|
||||
char const* const hex =
|
||||
detail::hexdigs[opt.lower_case];
|
||||
auto const encode = [end, hex](
|
||||
char*& dest,
|
||||
unsigned char c) noexcept
|
||||
{
|
||||
ignore_unused(end);
|
||||
*dest++ = '%';
|
||||
BOOST_ASSERT(dest != end);
|
||||
*dest++ = hex[c>>4];
|
||||
BOOST_ASSERT(dest != end);
|
||||
*dest++ = hex[c&0xf];
|
||||
};
|
||||
ignore_unused(end);
|
||||
|
||||
auto dest = dest_;
|
||||
auto const dest0 = dest;
|
||||
auto const last = s.end();
|
||||
std::size_t dn = 0;
|
||||
auto it = s.begin();
|
||||
|
||||
if(opt.space_as_plus)
|
||||
{
|
||||
while(it != last)
|
||||
{
|
||||
BOOST_ASSERT(dest != end);
|
||||
if(*it != '%')
|
||||
{
|
||||
if(*it == ' ')
|
||||
{
|
||||
*dest++ = '+';
|
||||
}
|
||||
else if(unreserved(*it))
|
||||
{
|
||||
*dest++ = *it;
|
||||
}
|
||||
else
|
||||
{
|
||||
encode(dest, *it);
|
||||
dn += 2;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dest++ = *it++;
|
||||
BOOST_ASSERT(dest != end);
|
||||
*dest++ = *it++;
|
||||
BOOST_ASSERT(dest != end);
|
||||
*dest++ = *it++;
|
||||
dn += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while(it != last)
|
||||
{
|
||||
BOOST_ASSERT(dest != end);
|
||||
if(*it != '%')
|
||||
{
|
||||
if(unreserved(*it))
|
||||
{
|
||||
*dest++ = *it;
|
||||
}
|
||||
else
|
||||
{
|
||||
encode(dest, *it);
|
||||
dn += 2;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dest++ = *it++;
|
||||
BOOST_ASSERT(dest != end);
|
||||
*dest++ = *it++;
|
||||
BOOST_ASSERT(dest != end);
|
||||
*dest++ = *it++;
|
||||
dn += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
dest_ = dest;
|
||||
return dest - dest0 - dn;
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_DETAIL_EXCEPT_HPP
|
||||
#define BOOST_URL_DETAIL_EXCEPT_HPP
|
||||
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <boost/assert/source_location.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
BOOST_URL_DECL void BOOST_NORETURN
|
||||
throw_system_error(
|
||||
system::error_code const& ec,
|
||||
source_location const& loc =
|
||||
BOOST_URL_POS);
|
||||
|
||||
BOOST_URL_DECL void BOOST_NORETURN
|
||||
throw_errc(
|
||||
boost::system::errc::errc_t ev,
|
||||
source_location const& loc =
|
||||
BOOST_URL_POS);
|
||||
|
||||
//-----
|
||||
|
||||
BOOST_URL_DECL void BOOST_NORETURN
|
||||
throw_invalid_argument(
|
||||
source_location const& loc =
|
||||
BOOST_URL_POS);
|
||||
|
||||
BOOST_URL_DECL void BOOST_NORETURN
|
||||
throw_length_error(
|
||||
source_location const& loc =
|
||||
BOOST_URL_POS);
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+340
@@ -0,0 +1,340 @@
|
||||
//
|
||||
// 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_DETAIL_FORMAT_ARGS_HPP
|
||||
#define BOOST_URL_DETAIL_FORMAT_ARGS_HPP
|
||||
|
||||
#include <boost/url/detail/encode.hpp>
|
||||
#include <boost/url/grammar/lut_chars.hpp>
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <array>
|
||||
|
||||
// This file implements functions and classes to
|
||||
// type-erase format arguments.
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
// state of the format string. It basically keeps
|
||||
// track of where we are in the format string.
|
||||
class format_parse_context
|
||||
{
|
||||
char const* begin_;
|
||||
char const* end_;
|
||||
std::size_t arg_id_ = 0;
|
||||
|
||||
public:
|
||||
constexpr
|
||||
format_parse_context(
|
||||
char const* first,
|
||||
char const* last,
|
||||
std::size_t arg_id = 0)
|
||||
: begin_( first )
|
||||
, end_( last )
|
||||
, arg_id_( arg_id )
|
||||
{}
|
||||
|
||||
constexpr
|
||||
format_parse_context(
|
||||
core::string_view fmt,
|
||||
std::size_t arg_id = 0)
|
||||
: format_parse_context(
|
||||
fmt.data(),
|
||||
fmt.data() + fmt.size(),
|
||||
arg_id )
|
||||
{}
|
||||
|
||||
constexpr
|
||||
char const*
|
||||
begin() const noexcept
|
||||
{
|
||||
return begin_;
|
||||
}
|
||||
|
||||
constexpr
|
||||
char const*
|
||||
end() const noexcept
|
||||
{
|
||||
return end_;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR
|
||||
void
|
||||
advance_to( char const* it )
|
||||
{
|
||||
begin_ = it;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
next_arg_id()
|
||||
{
|
||||
return arg_id_++;
|
||||
}
|
||||
};
|
||||
|
||||
// State of the destination string
|
||||
class format_context;
|
||||
class measure_context;
|
||||
struct ignore_format {};
|
||||
|
||||
template <class T>
|
||||
struct named_arg
|
||||
{
|
||||
core::string_view name;
|
||||
T const& value;
|
||||
|
||||
named_arg(core::string_view n, T const& v)
|
||||
: name(n)
|
||||
, value(v)
|
||||
{}
|
||||
};
|
||||
|
||||
// A type erased format argument
|
||||
class format_arg
|
||||
{
|
||||
void const* arg_;
|
||||
void (*measure_)(
|
||||
format_parse_context&,
|
||||
measure_context&,
|
||||
grammar::lut_chars const&,
|
||||
void const* );
|
||||
void (*fmt_)(
|
||||
format_parse_context&,
|
||||
format_context&,
|
||||
grammar::lut_chars const&,
|
||||
void const* );
|
||||
core::string_view name_;
|
||||
std::size_t value_ = 0;
|
||||
bool ignore_ = false;
|
||||
|
||||
template <class A>
|
||||
static
|
||||
void
|
||||
measure_impl(
|
||||
format_parse_context& pctx,
|
||||
measure_context& mctx,
|
||||
grammar::lut_chars const& cs,
|
||||
void const* a );
|
||||
|
||||
template <class A>
|
||||
static
|
||||
void
|
||||
format_impl(
|
||||
format_parse_context& pctx,
|
||||
format_context& fctx,
|
||||
grammar::lut_chars const& cs,
|
||||
void const* a );
|
||||
|
||||
public:
|
||||
template<class A>
|
||||
format_arg( A&& a );
|
||||
|
||||
template<class A>
|
||||
format_arg( named_arg<A>&& a );
|
||||
|
||||
template<class A>
|
||||
format_arg( core::string_view name, A&& a );
|
||||
|
||||
format_arg()
|
||||
: format_arg(ignore_format{})
|
||||
{}
|
||||
|
||||
explicit
|
||||
operator bool() const noexcept
|
||||
{
|
||||
return !ignore_;
|
||||
}
|
||||
|
||||
void
|
||||
measure(
|
||||
format_parse_context& pctx,
|
||||
measure_context& mctx,
|
||||
grammar::lut_chars const& cs)
|
||||
{
|
||||
measure_( pctx, mctx, cs, arg_ );
|
||||
}
|
||||
|
||||
void
|
||||
format(
|
||||
format_parse_context& pctx,
|
||||
format_context& fctx,
|
||||
grammar::lut_chars const& cs )
|
||||
{
|
||||
fmt_( pctx, fctx, cs, arg_ );
|
||||
}
|
||||
|
||||
core::string_view
|
||||
name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
};
|
||||
|
||||
// create temp stack storage for type erased args
|
||||
template< class... Args >
|
||||
std::array<format_arg, sizeof...(Args)>
|
||||
make_format_args( Args&&... args )
|
||||
{
|
||||
return {{ std::forward<Args>(args)... }};
|
||||
}
|
||||
|
||||
// reference to an array of format_args
|
||||
class format_args
|
||||
{
|
||||
format_arg const* p_{nullptr};
|
||||
std::size_t n_{0};
|
||||
|
||||
public:
|
||||
format_args(
|
||||
detail::format_arg const* first,
|
||||
detail::format_arg const* last ) noexcept
|
||||
: p_(first)
|
||||
, n_(static_cast<std::size_t>(last - first))
|
||||
{}
|
||||
|
||||
template < std::size_t N >
|
||||
format_args( std::array<format_arg, N> const& store ) noexcept
|
||||
: p_(store.data())
|
||||
, n_(store.size())
|
||||
{}
|
||||
|
||||
format_arg
|
||||
get( std::size_t i ) const noexcept
|
||||
{
|
||||
if (i < n_)
|
||||
return p_[i];
|
||||
return {};
|
||||
}
|
||||
|
||||
format_arg
|
||||
get( core::string_view name ) const noexcept
|
||||
{
|
||||
for (std::size_t i = 0; i < n_; ++i)
|
||||
{
|
||||
if (p_[i].name() == name)
|
||||
return p_[i];
|
||||
}
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
// define the format_context after format_args
|
||||
class format_context
|
||||
{
|
||||
format_args args_;
|
||||
char* out_;
|
||||
|
||||
public:
|
||||
format_context(
|
||||
char* out,
|
||||
format_args args )
|
||||
: args_( args )
|
||||
, out_( out )
|
||||
{}
|
||||
|
||||
format_args
|
||||
args() const noexcept
|
||||
{
|
||||
return args_;
|
||||
}
|
||||
|
||||
format_arg
|
||||
arg( std::size_t id ) const noexcept
|
||||
{
|
||||
return args_.get( id );
|
||||
}
|
||||
|
||||
format_arg
|
||||
arg( core::string_view name ) const noexcept
|
||||
{
|
||||
return args_.get( name );
|
||||
}
|
||||
|
||||
char*
|
||||
out()
|
||||
{
|
||||
return out_;
|
||||
}
|
||||
|
||||
void
|
||||
advance_to( char* it )
|
||||
{
|
||||
out_ = it;
|
||||
}
|
||||
};
|
||||
|
||||
// define the measure_context after format_args
|
||||
class measure_context
|
||||
{
|
||||
format_args args_;
|
||||
std::size_t out_;
|
||||
|
||||
public:
|
||||
measure_context(
|
||||
format_args args )
|
||||
: measure_context(0, args)
|
||||
{}
|
||||
|
||||
measure_context(
|
||||
std::size_t out,
|
||||
format_args args )
|
||||
: args_( args )
|
||||
, out_( out )
|
||||
{}
|
||||
|
||||
format_args
|
||||
args() const noexcept
|
||||
{
|
||||
return args_;
|
||||
}
|
||||
|
||||
format_arg
|
||||
arg( std::size_t id ) const noexcept
|
||||
{
|
||||
return args_.get( id );
|
||||
}
|
||||
|
||||
format_arg
|
||||
arg( core::string_view name ) const noexcept
|
||||
{
|
||||
return args_.get( name );
|
||||
}
|
||||
|
||||
std::size_t
|
||||
out()
|
||||
{
|
||||
return out_;
|
||||
}
|
||||
|
||||
void
|
||||
advance_to( std::size_t n )
|
||||
{
|
||||
out_ = n;
|
||||
}
|
||||
};
|
||||
|
||||
// fwd declare the formatter
|
||||
template <class T, class = void>
|
||||
struct formatter;
|
||||
|
||||
} // detail
|
||||
} // url
|
||||
} // boost
|
||||
|
||||
#include <boost/url/detail/impl/format_args.hpp>
|
||||
|
||||
#endif
|
||||
+416
@@ -0,0 +1,416 @@
|
||||
//
|
||||
// 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_DETAIL_IMPL_FORMAT_ARGS_HPP
|
||||
#define BOOST_URL_DETAIL_IMPL_FORMAT_ARGS_HPP
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
template<
|
||||
class A,
|
||||
typename std::enable_if<
|
||||
!std::is_integral<
|
||||
typename std::decay<A>::type>::value,
|
||||
int>::type = 0>
|
||||
std::size_t
|
||||
get_uvalue( A&& )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<
|
||||
class A,
|
||||
typename std::enable_if<
|
||||
std::is_integral<
|
||||
typename std::decay<A>::type>::value &&
|
||||
std::is_signed<
|
||||
typename std::decay<A>::type>::value,
|
||||
int>::type = 0>
|
||||
std::size_t
|
||||
get_uvalue( A&& a )
|
||||
{
|
||||
if (a > 0)
|
||||
return static_cast<std::size_t>(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<
|
||||
class A,
|
||||
typename std::enable_if<
|
||||
std::is_integral<
|
||||
typename std::decay<A>::type>::value &&
|
||||
std::is_unsigned<
|
||||
typename std::decay<A>::type>::value,
|
||||
int>::type = 0>
|
||||
std::size_t
|
||||
get_uvalue( A&& a )
|
||||
{
|
||||
return static_cast<std::size_t>(a);
|
||||
}
|
||||
|
||||
BOOST_URL_DECL
|
||||
std::size_t
|
||||
get_uvalue( core::string_view a );
|
||||
|
||||
BOOST_URL_DECL
|
||||
std::size_t
|
||||
get_uvalue( char a );
|
||||
|
||||
template<class A>
|
||||
format_arg::
|
||||
format_arg( A&& a )
|
||||
: arg_( &a )
|
||||
, measure_( &measure_impl<A> )
|
||||
, fmt_( &format_impl<A> )
|
||||
, value_( get_uvalue(std::forward<A>(a) ))
|
||||
, ignore_( std::is_same<A, ignore_format>::value )
|
||||
{}
|
||||
|
||||
template<class A>
|
||||
format_arg::
|
||||
format_arg( named_arg<A>&& a )
|
||||
: arg_( &a.value )
|
||||
, measure_( &measure_impl<A> )
|
||||
, fmt_( &format_impl<A> )
|
||||
, name_( a.name )
|
||||
, value_( get_uvalue(a.value))
|
||||
{}
|
||||
|
||||
template<class A>
|
||||
format_arg::
|
||||
format_arg( core::string_view name, A&& a )
|
||||
: arg_( &a )
|
||||
, measure_( &measure_impl<A> )
|
||||
, fmt_( &format_impl<A> )
|
||||
, name_( name )
|
||||
, value_( get_uvalue(a) )
|
||||
{}
|
||||
|
||||
// define the type-erased implementations that
|
||||
// depends on everything: the context types,
|
||||
// formatters, and type erased args
|
||||
template <class A>
|
||||
void
|
||||
format_arg::
|
||||
measure_impl(
|
||||
format_parse_context& pctx,
|
||||
measure_context& mctx,
|
||||
grammar::lut_chars const& cs,
|
||||
void const* a )
|
||||
{
|
||||
using ref_t = typename std::remove_reference<A>::type;
|
||||
A const& ref = *static_cast<ref_t*>(
|
||||
const_cast<void*>( a ) );
|
||||
formatter<ref_t> f;
|
||||
pctx.advance_to( f.parse(pctx) );
|
||||
mctx.advance_to( f.measure( ref, mctx, cs ) );
|
||||
}
|
||||
|
||||
template <class A>
|
||||
void
|
||||
format_arg::
|
||||
format_impl(
|
||||
format_parse_context& pctx,
|
||||
format_context& fctx,
|
||||
grammar::lut_chars const& cs,
|
||||
void const* a )
|
||||
{
|
||||
using ref_t = typename std::remove_reference<A>::type;
|
||||
A const& ref = *static_cast<ref_t*>(
|
||||
const_cast<void*>( a ) );
|
||||
formatter<ref_t> f;
|
||||
pctx.advance_to( f.parse(pctx) );
|
||||
fctx.advance_to( f.format( ref, fctx, cs ) );
|
||||
}
|
||||
|
||||
// We point to formatter<ignore_format> where
|
||||
// the format_arg variant would store monostate
|
||||
template <>
|
||||
struct formatter<ignore_format>
|
||||
{
|
||||
public:
|
||||
char const*
|
||||
parse(format_parse_context& ctx) const
|
||||
{
|
||||
return parse_empty_spec(
|
||||
ctx.begin(), ctx.end());
|
||||
}
|
||||
|
||||
std::size_t
|
||||
measure(
|
||||
ignore_format,
|
||||
measure_context& ctx,
|
||||
grammar::lut_chars const&) const
|
||||
{
|
||||
return ctx.out();
|
||||
}
|
||||
|
||||
char*
|
||||
format(
|
||||
ignore_format,
|
||||
format_context& ctx,
|
||||
grammar::lut_chars const&) const
|
||||
{
|
||||
return ctx.out();
|
||||
}
|
||||
|
||||
// We ignore the modifiers in all replacements
|
||||
// for now
|
||||
static
|
||||
char const*
|
||||
parse_empty_spec(
|
||||
char const* it,
|
||||
char const* end)
|
||||
{
|
||||
// [it, end] -> "} suffix"
|
||||
BOOST_ASSERT(it != end);
|
||||
ignore_unused(end);
|
||||
// Should be always empty/valid as an
|
||||
// implementation detail
|
||||
BOOST_ASSERT(*it == '}');
|
||||
/*
|
||||
if (*it != '}')
|
||||
urls::detail::throw_invalid_argument();
|
||||
*/
|
||||
return it;
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
std::size_t
|
||||
measure_one(
|
||||
char c,
|
||||
grammar::lut_chars const& unreserved)
|
||||
{
|
||||
// '%' must be reserved
|
||||
BOOST_ASSERT(! unreserved('%'));
|
||||
return 1 + !unreserved(c) * 2;
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
encode_one(
|
||||
char*& out,
|
||||
char c,
|
||||
grammar::lut_chars const& unreserved)
|
||||
{
|
||||
// '%' must be reserved
|
||||
BOOST_ASSERT(! unreserved('%'));
|
||||
if(unreserved(c))
|
||||
{
|
||||
*out++ = c;
|
||||
return;
|
||||
}
|
||||
*out++ = '%';
|
||||
*out++ = urls::detail::hexdigs[0][c>>4];
|
||||
*out++ = urls::detail::hexdigs[0][c&0xf];
|
||||
}
|
||||
|
||||
// get an unsigned value from format_args
|
||||
BOOST_URL_DECL
|
||||
void
|
||||
get_width_from_args(
|
||||
std::size_t arg_idx,
|
||||
core::string_view arg_name,
|
||||
format_args args,
|
||||
std::size_t& w);
|
||||
|
||||
// formatter for string view
|
||||
template <>
|
||||
struct formatter<core::string_view>
|
||||
{
|
||||
private:
|
||||
char fill = ' ';
|
||||
char align = '\0';
|
||||
std::size_t width = 0;
|
||||
std::size_t width_idx = std::size_t(-1);
|
||||
core::string_view width_name;
|
||||
|
||||
public:
|
||||
BOOST_URL_DECL
|
||||
char const*
|
||||
parse(format_parse_context& ctx);
|
||||
|
||||
BOOST_URL_DECL
|
||||
std::size_t
|
||||
measure(
|
||||
core::string_view str,
|
||||
measure_context& ctx,
|
||||
grammar::lut_chars const& cs) const;
|
||||
|
||||
BOOST_URL_DECL
|
||||
char*
|
||||
format(
|
||||
core::string_view str,
|
||||
format_context& ctx,
|
||||
grammar::lut_chars const& cs) const;
|
||||
};
|
||||
|
||||
// formatter for anything convertible to a
|
||||
// string view
|
||||
template <class T>
|
||||
struct formatter<
|
||||
T, typename std::enable_if<
|
||||
std::is_convertible<
|
||||
T, core::string_view>::value>::type>
|
||||
{
|
||||
formatter<core::string_view> impl_;
|
||||
|
||||
public:
|
||||
char const*
|
||||
parse(format_parse_context& ctx)
|
||||
{
|
||||
return impl_.parse(ctx);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
measure(
|
||||
core::string_view str,
|
||||
measure_context& ctx,
|
||||
grammar::lut_chars const& cs) const
|
||||
{
|
||||
return impl_.measure(str, ctx, cs);
|
||||
}
|
||||
|
||||
char*
|
||||
format(core::string_view str, format_context& ctx, grammar::lut_chars const& cs) const
|
||||
{
|
||||
return impl_.format(str, ctx, cs);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct formatter<char>
|
||||
{
|
||||
formatter<core::string_view> impl_;
|
||||
|
||||
public:
|
||||
char const*
|
||||
parse(format_parse_context& ctx)
|
||||
{
|
||||
return impl_.parse(ctx);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
measure(
|
||||
char c,
|
||||
measure_context& ctx,
|
||||
grammar::lut_chars const& cs) const
|
||||
{
|
||||
return impl_.measure({&c, 1}, ctx, cs);
|
||||
}
|
||||
|
||||
char*
|
||||
format(
|
||||
char c,
|
||||
format_context& ctx,
|
||||
grammar::lut_chars const& cs) const
|
||||
{
|
||||
return impl_.format({&c, 1}, ctx, cs);
|
||||
}
|
||||
};
|
||||
|
||||
// formatters for a single integer
|
||||
class integer_formatter_impl
|
||||
{
|
||||
char fill = ' ';
|
||||
char align = '\0';
|
||||
char sign = '-';
|
||||
bool zeros = false;
|
||||
std::size_t width = 0;
|
||||
std::size_t width_idx = std::size_t(-1);
|
||||
core::string_view width_name;
|
||||
|
||||
public:
|
||||
BOOST_URL_DECL
|
||||
char const*
|
||||
parse(format_parse_context& ctx);
|
||||
|
||||
BOOST_URL_DECL
|
||||
std::size_t
|
||||
measure(
|
||||
unsigned long long int v,
|
||||
measure_context& ctx,
|
||||
grammar::lut_chars const& cs) const;
|
||||
|
||||
BOOST_URL_DECL
|
||||
std::size_t
|
||||
measure(
|
||||
long long int v,
|
||||
measure_context& ctx,
|
||||
grammar::lut_chars const& cs) const;
|
||||
|
||||
BOOST_URL_DECL
|
||||
char*
|
||||
format(
|
||||
unsigned long long int v,
|
||||
format_context& ctx,
|
||||
grammar::lut_chars const& cs) const;
|
||||
|
||||
BOOST_URL_DECL
|
||||
char*
|
||||
format(
|
||||
long long int v,
|
||||
format_context& ctx,
|
||||
grammar::lut_chars const& cs) const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct formatter<
|
||||
T, typename std::enable_if<
|
||||
mp11::mp_contains<mp11::mp_list<
|
||||
short int,
|
||||
int,
|
||||
long int,
|
||||
long long int,
|
||||
unsigned short int,
|
||||
unsigned int,
|
||||
unsigned long int,
|
||||
unsigned long long int>, T>::value>::type>
|
||||
{
|
||||
private:
|
||||
integer_formatter_impl impl_;
|
||||
using base_value_type = typename std::conditional<
|
||||
std::is_unsigned<T>::value,
|
||||
unsigned long long int,
|
||||
long long int
|
||||
>::type;
|
||||
|
||||
public:
|
||||
char const*
|
||||
parse(format_parse_context& ctx)
|
||||
{
|
||||
return impl_.parse(ctx);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
measure(
|
||||
T v,
|
||||
measure_context& ctx,
|
||||
grammar::lut_chars const& cs) const
|
||||
{
|
||||
return impl_.measure(
|
||||
static_cast<base_value_type>(v), ctx, cs);
|
||||
}
|
||||
|
||||
char*
|
||||
format(T v, format_context& ctx, grammar::lut_chars const& cs) const
|
||||
{
|
||||
return impl_.format(
|
||||
static_cast<base_value_type>(v), ctx, cs);
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // url
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_DETAIL_MOVE_CHARS_HPP
|
||||
#define BOOST_URL_DETAIL_MOVE_CHARS_HPP
|
||||
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
// Moves characters, and adjusts any passed
|
||||
// views if they point to any moved characters.
|
||||
|
||||
// true if s completely overlapped by buf
|
||||
inline
|
||||
bool
|
||||
is_overlapping(
|
||||
core::string_view buf,
|
||||
core::string_view s) noexcept
|
||||
{
|
||||
auto const b0 = buf.data();
|
||||
auto const e0 = b0 + buf.size();
|
||||
auto const b1 = s.data();
|
||||
auto const e1 = b1 + s.size();
|
||||
auto const less_equal =
|
||||
std::less_equal<char const*>();
|
||||
if(less_equal(e0, b1))
|
||||
return false;
|
||||
if(less_equal(e1, b0))
|
||||
return false;
|
||||
// partial overlap is undefined
|
||||
BOOST_ASSERT(less_equal(e1, e0));
|
||||
BOOST_ASSERT(less_equal(b0, b1));
|
||||
return true;
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
move_chars_impl(
|
||||
std::ptrdiff_t,
|
||||
core::string_view const&) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
template<class... Sn>
|
||||
void
|
||||
move_chars_impl(
|
||||
std::ptrdiff_t d,
|
||||
core::string_view const& buf,
|
||||
core::string_view& s,
|
||||
Sn&... sn) noexcept
|
||||
{
|
||||
if(is_overlapping(buf, s))
|
||||
s = {s.data() + d, s.size()};
|
||||
move_chars_impl(d, buf, sn...);
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
void
|
||||
move_chars(
|
||||
char* dest,
|
||||
char const* src,
|
||||
std::size_t n,
|
||||
Args&... args) noexcept
|
||||
{
|
||||
core::string_view buf(src, n);
|
||||
move_chars_impl(
|
||||
dest - src,
|
||||
core::string_view(src, n),
|
||||
args...);
|
||||
std::memmove(
|
||||
dest, src, n);
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_DETAIL_NORMALIZED_HPP
|
||||
#define BOOST_URL_DETAIL_NORMALIZED_HPP
|
||||
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/url/segments_encoded_view.hpp>
|
||||
#include <boost/url/detail/normalize.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
class fnv_1a
|
||||
{
|
||||
public:
|
||||
using digest_type = std::size_t;
|
||||
|
||||
#if BOOST_URL_ARCH == 64
|
||||
static constexpr std::size_t const prime =
|
||||
static_cast<std::size_t>(0x100000001B3ULL);
|
||||
static constexpr std::size_t init_hash =
|
||||
static_cast<std::size_t>(0xcbf29ce484222325ULL);
|
||||
#else
|
||||
static constexpr std::size_t const prime =
|
||||
static_cast<std::size_t>(0x01000193UL);
|
||||
static constexpr std::size_t init_hash =
|
||||
static_cast<std::size_t>(0x811C9DC5UL);
|
||||
#endif
|
||||
|
||||
explicit
|
||||
fnv_1a(std::size_t salt) noexcept
|
||||
: h_(init_hash + salt)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
put(char c) noexcept
|
||||
{
|
||||
h_ ^= c;
|
||||
h_ *= prime;
|
||||
}
|
||||
|
||||
void
|
||||
put(core::string_view s) noexcept
|
||||
{
|
||||
for (char c: s)
|
||||
{
|
||||
put(c);
|
||||
}
|
||||
}
|
||||
|
||||
digest_type
|
||||
digest() const noexcept
|
||||
{
|
||||
return h_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t h_;
|
||||
};
|
||||
|
||||
void
|
||||
pop_encoded_front(
|
||||
core::string_view& s,
|
||||
char& c,
|
||||
std::size_t& n) noexcept;
|
||||
|
||||
// compare two core::string_views as if they are both
|
||||
// percent-decoded
|
||||
int
|
||||
compare_encoded(
|
||||
core::string_view lhs,
|
||||
core::string_view rhs) noexcept;
|
||||
|
||||
// digest a core::string_view as if it were
|
||||
// percent-decoded
|
||||
void
|
||||
digest_encoded(
|
||||
core::string_view s,
|
||||
fnv_1a& hasher) noexcept;
|
||||
|
||||
void
|
||||
digest(
|
||||
core::string_view s,
|
||||
fnv_1a& hasher) noexcept;
|
||||
|
||||
// check if core::string_view lhs starts with core::string_view
|
||||
// rhs as if they are both percent-decoded. If
|
||||
// lhs starts with rhs, return number of chars
|
||||
// matched in the encoded core::string_view
|
||||
std::size_t
|
||||
path_starts_with(
|
||||
core::string_view lhs,
|
||||
core::string_view rhs) noexcept;
|
||||
|
||||
// check if core::string_view lhs ends with core::string_view
|
||||
// rhs as if they are both percent-decoded. If
|
||||
// lhs ends with rhs, return number of chars
|
||||
// matched in the encoded core::string_view
|
||||
std::size_t
|
||||
path_ends_with(
|
||||
core::string_view lhs,
|
||||
core::string_view rhs) noexcept;
|
||||
|
||||
// compare two core::string_views as if they are both
|
||||
// percent-decoded and lowercase
|
||||
int
|
||||
ci_compare_encoded(
|
||||
core::string_view lhs,
|
||||
core::string_view rhs) noexcept;
|
||||
|
||||
// digest a core::string_view as if it were decoded
|
||||
// and lowercase
|
||||
void
|
||||
ci_digest_encoded(
|
||||
core::string_view s,
|
||||
fnv_1a& hasher) noexcept;
|
||||
|
||||
// compare two ascii core::string_views
|
||||
int
|
||||
compare(
|
||||
core::string_view lhs,
|
||||
core::string_view rhs) noexcept;
|
||||
|
||||
// compare two core::string_views as if they are both
|
||||
// lowercase
|
||||
int
|
||||
ci_compare(
|
||||
core::string_view lhs,
|
||||
core::string_view rhs) noexcept;
|
||||
|
||||
// digest a core::string_view as if it were lowercase
|
||||
void
|
||||
ci_digest(
|
||||
core::string_view s,
|
||||
fnv_1a& hasher) noexcept;
|
||||
|
||||
BOOST_URL_DECL
|
||||
std::size_t
|
||||
remove_dot_segments(
|
||||
char* dest,
|
||||
char const* end,
|
||||
core::string_view s) noexcept;
|
||||
|
||||
void
|
||||
pop_last_segment(
|
||||
core::string_view& s,
|
||||
core::string_view& c,
|
||||
std::size_t& level,
|
||||
bool r) noexcept;
|
||||
|
||||
char
|
||||
path_pop_back( core::string_view& s );
|
||||
|
||||
void
|
||||
normalized_path_digest(
|
||||
core::string_view s,
|
||||
bool remove_unmatched,
|
||||
fnv_1a& hasher) noexcept;
|
||||
|
||||
int
|
||||
segments_compare(
|
||||
segments_encoded_view seg0,
|
||||
segments_encoded_view seg1) noexcept;
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// 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_DETAIL_OPTIONAL_STRING_HPP
|
||||
#define BOOST_URL_DETAIL_OPTIONAL_STRING_HPP
|
||||
|
||||
#include <boost/url/detail/string_view.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
struct no_value_t;
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
struct optional_string
|
||||
{
|
||||
core::string_view s;
|
||||
bool b = false;
|
||||
};
|
||||
|
||||
template <class String>
|
||||
typename std::enable_if<
|
||||
std::is_convertible<String, core::string_view>::value,
|
||||
optional_string>::type
|
||||
get_optional_string(
|
||||
String const& s)
|
||||
{
|
||||
optional_string r;
|
||||
r.s = s;
|
||||
r.b = true;
|
||||
return r;
|
||||
}
|
||||
|
||||
template <class T, class = void>
|
||||
struct is_dereferenceable : std::false_type
|
||||
{};
|
||||
|
||||
template <class T>
|
||||
struct is_dereferenceable<
|
||||
T,
|
||||
void_t<
|
||||
decltype(*std::declval<T>())
|
||||
>> : std::true_type
|
||||
{};
|
||||
|
||||
template <class OptionalString>
|
||||
typename std::enable_if<
|
||||
!std::is_convertible<OptionalString, core::string_view>::value,
|
||||
optional_string>::type
|
||||
get_optional_string(
|
||||
OptionalString const& opt)
|
||||
{
|
||||
// If this goes off, it means the rule
|
||||
// passed in did not meet the requirements.
|
||||
// Please check the documentation of functions
|
||||
// that call get_optional_string.
|
||||
static_assert(
|
||||
is_dereferenceable<OptionalString>::value &&
|
||||
std::is_constructible<bool, OptionalString>::value &&
|
||||
!std::is_convertible<OptionalString, core::string_view>::value &&
|
||||
std::is_convertible<typename std::decay<decltype(*std::declval<OptionalString>())>::type, core::string_view>::value,
|
||||
"OptionalString requirements not met");
|
||||
optional_string r;
|
||||
r.s = opt ? detail::to_sv(*opt) : core::string_view{};
|
||||
r.b = static_cast<bool>(opt);
|
||||
return r;
|
||||
}
|
||||
|
||||
inline
|
||||
optional_string
|
||||
get_optional_string(
|
||||
std::nullptr_t)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
inline
|
||||
optional_string
|
||||
get_optional_string(
|
||||
no_value_t const&)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_DETAIL_OVER_ALLOCATOR_HPP
|
||||
#define BOOST_URL_DETAIL_OVER_ALLOCATOR_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/empty_value.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/type_traits/is_final.hpp>
|
||||
#include <boost/type_traits/type_with_alignment.hpp>
|
||||
#ifdef BOOST_NO_CXX11_ALLOCATOR
|
||||
# include <boost/core/allocator_traits.hpp>
|
||||
#endif
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
// This is a workaround for allocator_traits
|
||||
// implementations which falsely claim C++11
|
||||
// compatibility.
|
||||
#ifdef BOOST_NO_CXX11_ALLOCATOR
|
||||
template<class Alloc>
|
||||
using allocator_traits =
|
||||
boost::allocator_traits<Alloc>;
|
||||
#else
|
||||
template<class Alloc>
|
||||
using allocator_traits = std::allocator_traits<Alloc>;
|
||||
#endif
|
||||
|
||||
template<class T, class Allocator>
|
||||
class over_allocator
|
||||
: private empty_value<Allocator>
|
||||
{
|
||||
template<class U, class OtherAlloc>
|
||||
friend class over_allocator;
|
||||
|
||||
std::size_t extra_;
|
||||
|
||||
public:
|
||||
using is_always_equal = std::false_type;
|
||||
using value_type = typename
|
||||
allocator_traits<typename allocator_traits<
|
||||
Allocator>::template rebind_alloc<T>>::value_type;
|
||||
using pointer = typename
|
||||
allocator_traits<typename allocator_traits<
|
||||
Allocator>::template rebind_alloc<T>>::pointer;
|
||||
using const_pointer = typename
|
||||
allocator_traits<typename allocator_traits<
|
||||
Allocator>::template rebind_alloc<T>>::const_pointer;
|
||||
using size_type = typename
|
||||
allocator_traits<typename allocator_traits<
|
||||
Allocator>::template rebind_alloc<T>>::size_type;
|
||||
using difference_type = typename
|
||||
allocator_traits<typename allocator_traits<
|
||||
Allocator>::template rebind_alloc<T>>::difference_type;
|
||||
|
||||
template<class U>
|
||||
struct rebind
|
||||
{
|
||||
using other = over_allocator<U, Allocator>;
|
||||
};
|
||||
|
||||
over_allocator(
|
||||
std::size_t extra,
|
||||
Allocator const& alloc)
|
||||
: empty_value<Allocator>(
|
||||
empty_init, alloc)
|
||||
, extra_(extra)
|
||||
{
|
||||
}
|
||||
|
||||
template<class U>
|
||||
over_allocator(over_allocator<U, Allocator> const& other) noexcept
|
||||
: empty_value<Allocator>(
|
||||
empty_init, other.get())
|
||||
, extra_(other.extra_)
|
||||
{
|
||||
}
|
||||
|
||||
pointer
|
||||
allocate(size_type n)
|
||||
{
|
||||
BOOST_ASSERT(n == 1);
|
||||
using U = typename boost::type_with_alignment<
|
||||
alignof(value_type)>::type;
|
||||
auto constexpr S = sizeof(U);
|
||||
using A = typename allocator_traits<
|
||||
Allocator>::template rebind_alloc<U>;
|
||||
A a(this->get());
|
||||
return reinterpret_cast<pointer>(
|
||||
std::allocator_traits<A>::allocate(a,
|
||||
(n * sizeof(value_type) + extra_ + S - 1) / S));
|
||||
}
|
||||
|
||||
void
|
||||
deallocate(pointer p, size_type n)
|
||||
{
|
||||
BOOST_ASSERT(n == 1);
|
||||
using U = typename boost::type_with_alignment<
|
||||
alignof(value_type)>::type;
|
||||
auto constexpr S = sizeof(U);
|
||||
using A = typename allocator_traits<
|
||||
Allocator>::template rebind_alloc<U>;
|
||||
A a{this->get()};
|
||||
std::allocator_traits<A>::deallocate(a,
|
||||
reinterpret_cast<U*>(p),
|
||||
(n * sizeof(value_type) + extra_ + S - 1) / S);
|
||||
}
|
||||
|
||||
#if defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 60000
|
||||
template<class U, class... Args>
|
||||
void
|
||||
construct(U* ptr, Args&&... args)
|
||||
{
|
||||
::new((void*)ptr) U(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class U>
|
||||
void
|
||||
destroy(U* ptr)
|
||||
{
|
||||
ptr->~U();
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class U>
|
||||
friend
|
||||
bool
|
||||
operator==(
|
||||
over_allocator const& lhs,
|
||||
over_allocator<U, Allocator> const& rhs)
|
||||
{
|
||||
return
|
||||
lhs.get() == rhs.get() &&
|
||||
lhs.extra_ == rhs.extra_;
|
||||
}
|
||||
|
||||
template<class U>
|
||||
friend
|
||||
bool
|
||||
operator!=(
|
||||
over_allocator const& lhs,
|
||||
over_allocator<U, Allocator> const& rhs)
|
||||
{
|
||||
return ! (lhs == rhs);
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_DETAIL_PARAMS_ITER_IMPL_HPP
|
||||
#define BOOST_URL_DETAIL_PARAMS_ITER_IMPL_HPP
|
||||
|
||||
#include <boost/url/param.hpp>
|
||||
#include <boost/url/detail/parts_base.hpp>
|
||||
#include <boost/url/detail/url_impl.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
struct BOOST_URL_DECL params_iter_impl
|
||||
: parts_base
|
||||
{
|
||||
query_ref ref;
|
||||
std::size_t index = 0;
|
||||
std::size_t pos;
|
||||
std::size_t nk;
|
||||
std::size_t nv;
|
||||
std::size_t dk;
|
||||
std::size_t dv;
|
||||
|
||||
params_iter_impl() = default;
|
||||
params_iter_impl(
|
||||
params_iter_impl const&) = default;
|
||||
params_iter_impl& operator=(
|
||||
params_iter_impl const&) = default;
|
||||
|
||||
// begin
|
||||
params_iter_impl(
|
||||
query_ref const&) noexcept;
|
||||
|
||||
// end
|
||||
params_iter_impl(
|
||||
query_ref const&,
|
||||
int) noexcept;
|
||||
|
||||
// at index
|
||||
params_iter_impl(
|
||||
query_ref const&,
|
||||
std::size_t,
|
||||
std::size_t) noexcept;
|
||||
void setup() noexcept;
|
||||
void increment() noexcept;
|
||||
void decrement() noexcept;
|
||||
param_pct_view
|
||||
dereference() const noexcept;
|
||||
pct_string_view key() const noexcept;
|
||||
|
||||
auto
|
||||
next() const noexcept ->
|
||||
params_iter_impl
|
||||
{
|
||||
auto next = *this;
|
||||
next.increment();
|
||||
return next;
|
||||
}
|
||||
|
||||
bool
|
||||
equal(
|
||||
params_iter_impl const&
|
||||
other) const noexcept
|
||||
{
|
||||
// different containers
|
||||
BOOST_ASSERT(ref.alias_of(other.ref));
|
||||
return index == other.index;
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_DETAIL_PARTS_BASE_HPP
|
||||
#define BOOST_URL_DETAIL_PARTS_BASE_HPP
|
||||
|
||||
#include <boost/url/error.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
// mix-in to provide part
|
||||
// constants and variables
|
||||
struct parts_base
|
||||
{
|
||||
enum
|
||||
{
|
||||
id_scheme = -1, // trailing ':'
|
||||
id_user, // leading "//"
|
||||
id_pass, // leading ':', trailing '@'
|
||||
id_host,
|
||||
id_port, // leading ':'
|
||||
id_path,
|
||||
id_query, // leading '?'
|
||||
id_frag, // leading '#'
|
||||
id_end // one past the end
|
||||
};
|
||||
|
||||
enum class from : char {
|
||||
// this belongs to a string
|
||||
string = 0,
|
||||
// this belongs to url_base
|
||||
// segments/params containers point to
|
||||
// another url
|
||||
url = 1,
|
||||
// this belongs to authority_view
|
||||
// id_user does not have the leading "//"
|
||||
authority = 2,
|
||||
};
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_DETAIL_PATH_HPP
|
||||
#define BOOST_URL_DETAIL_PATH_HPP
|
||||
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
// Return the number of characters at
|
||||
// the front of the path that are reserved
|
||||
inline
|
||||
std::size_t
|
||||
path_prefix(
|
||||
char const* p,
|
||||
std::size_t n) noexcept
|
||||
{
|
||||
switch(n)
|
||||
{
|
||||
case 0:
|
||||
return 0;
|
||||
|
||||
case 1:
|
||||
if(p[0] == '/')
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
case 2:
|
||||
if(p[0] == '/')
|
||||
return 1;
|
||||
if( p[0] == '.' &&
|
||||
p[1] == '/')
|
||||
return 2;
|
||||
return 0;
|
||||
|
||||
default:
|
||||
if(p[0] == '/')
|
||||
{
|
||||
if( p[1] == '.' &&
|
||||
p[2] == '/')
|
||||
return 3;
|
||||
return 1;
|
||||
}
|
||||
if( p[0] == '.' &&
|
||||
p[1] == '/')
|
||||
return 2;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// VFALCO DEPRECATED
|
||||
inline
|
||||
std::size_t
|
||||
path_prefix(
|
||||
core::string_view s) noexcept
|
||||
{
|
||||
return path_prefix(
|
||||
s.data(), s.size());
|
||||
}
|
||||
|
||||
// returns the number of adjusted
|
||||
// segments based on the malleable prefix.
|
||||
inline
|
||||
std::size_t
|
||||
path_segments(
|
||||
core::string_view s,
|
||||
std::size_t nseg) noexcept
|
||||
{
|
||||
switch(s.size())
|
||||
{
|
||||
case 0:
|
||||
BOOST_ASSERT(nseg == 0);
|
||||
return 0;
|
||||
|
||||
case 1:
|
||||
BOOST_ASSERT(nseg == 1);
|
||||
if(s[0] == '/')
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
case 2:
|
||||
if(s[0] == '/')
|
||||
return nseg;
|
||||
if( s[0] == '.' &&
|
||||
s[1] == '/')
|
||||
{
|
||||
BOOST_ASSERT(nseg > 1);
|
||||
return nseg - 1;
|
||||
}
|
||||
return nseg;
|
||||
|
||||
default:
|
||||
if(s[0] == '/')
|
||||
{
|
||||
if( s[1] == '.' &&
|
||||
s[2] == '/')
|
||||
{
|
||||
BOOST_ASSERT(nseg > 1);
|
||||
return nseg - 1;
|
||||
}
|
||||
return nseg;
|
||||
}
|
||||
if( s[0] == '.' &&
|
||||
s[1] == '/')
|
||||
{
|
||||
BOOST_ASSERT(nseg > 1);
|
||||
return nseg - 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return nseg;
|
||||
}
|
||||
|
||||
// Trim reserved characters from
|
||||
// the front of the path.
|
||||
inline
|
||||
core::string_view
|
||||
clean_path(
|
||||
core::string_view s) noexcept
|
||||
{
|
||||
s.remove_prefix(
|
||||
path_prefix(s));
|
||||
return s;
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// 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_DETAIL_PATTERN_HPP
|
||||
#define BOOST_URL_DETAIL_PATTERN_HPP
|
||||
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <boost/url/url_base.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
|
||||
// This file includes functions and classes
|
||||
// to parse uri templates or format strings
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
class format_args;
|
||||
|
||||
struct pattern
|
||||
{
|
||||
core::string_view scheme;
|
||||
core::string_view user;
|
||||
core::string_view pass;
|
||||
core::string_view host;
|
||||
core::string_view port;
|
||||
core::string_view path;
|
||||
core::string_view query;
|
||||
core::string_view frag;
|
||||
|
||||
bool has_authority = false;
|
||||
bool has_user = false;
|
||||
bool has_pass = false;
|
||||
bool has_port = false;
|
||||
bool has_query = false;
|
||||
bool has_frag = false;
|
||||
|
||||
BOOST_URL_DECL
|
||||
void
|
||||
apply(
|
||||
url_base& u,
|
||||
format_args const& args) const;
|
||||
};
|
||||
|
||||
BOOST_URL_DECL
|
||||
system::result<pattern>
|
||||
parse_pattern(
|
||||
core::string_view s);
|
||||
|
||||
} // detail
|
||||
} // url
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// 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_DETAIL_PCT_FORMAT_HPP
|
||||
#define BOOST_URL_DETAIL_PCT_FORMAT_HPP
|
||||
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/url/url.hpp>
|
||||
#include <boost/url/grammar/lut_chars.hpp>
|
||||
#include <boost/url/detail/format_args.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
// measure a single string
|
||||
BOOST_URL_DECL
|
||||
std::size_t
|
||||
pct_vmeasure(
|
||||
grammar::lut_chars const& cs,
|
||||
format_parse_context& pctx,
|
||||
measure_context& mctx);
|
||||
|
||||
// format a single string
|
||||
BOOST_URL_DECL
|
||||
char*
|
||||
pct_vformat(
|
||||
grammar::lut_chars const& cs,
|
||||
format_parse_context& pctx,
|
||||
format_context& fctx);
|
||||
|
||||
} // detail
|
||||
} // url
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_DETAIL_PRINT_HPP
|
||||
#define BOOST_URL_DETAIL_PRINT_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
// std::uint64_t
|
||||
// 18446744073709551615
|
||||
// 1 2
|
||||
template<class T>
|
||||
struct printed
|
||||
: std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
// 16-bit unsigned
|
||||
template<>
|
||||
class printed<std::uint16_t>
|
||||
: std::false_type
|
||||
{
|
||||
char n_;
|
||||
char buf_[5];
|
||||
|
||||
public:
|
||||
printed(std::uint16_t n)
|
||||
{
|
||||
char* it =
|
||||
buf_ + sizeof(buf_);
|
||||
if(n == 0)
|
||||
{
|
||||
*--it = '0';
|
||||
n_ = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(n > 0)
|
||||
{
|
||||
*--it = '0' + (n % 10);
|
||||
n /= 10;
|
||||
}
|
||||
n_ = static_cast<char>(
|
||||
sizeof(buf_) - (
|
||||
it - buf_));
|
||||
}
|
||||
}
|
||||
|
||||
core::string_view
|
||||
string() const noexcept
|
||||
{
|
||||
return core::string_view(buf_ +
|
||||
sizeof(buf_) - n_, n_);
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
printed<T>
|
||||
make_printed(T t)
|
||||
{
|
||||
return printed<T>(t);
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// 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_DETAIL_REPLACEMENT_FIELD_RULE_HPP
|
||||
#define BOOST_URL_DETAIL_REPLACEMENT_FIELD_RULE_HPP
|
||||
|
||||
#include <boost/url/error.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/url/grammar/variant_rule.hpp>
|
||||
#include <boost/url/grammar/unsigned_rule.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
// replacement_field ::= "{" [arg_id] [":" format_spec "}"
|
||||
struct replacement_field_rule_t
|
||||
{
|
||||
using value_type = core::string_view;
|
||||
|
||||
BOOST_URL_DECL
|
||||
system::result<value_type>
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const noexcept;
|
||||
};
|
||||
|
||||
constexpr replacement_field_rule_t replacement_field_rule{};
|
||||
|
||||
// identifier ::= id_start id_continue*
|
||||
// id_start ::= "a"..."z" | "A"..."Z" | "_"
|
||||
// id_continue ::= id_start | digit
|
||||
struct identifier_rule_t
|
||||
{
|
||||
using value_type = core::string_view;
|
||||
|
||||
BOOST_URL_DECL
|
||||
system::result<value_type>
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const noexcept;
|
||||
};
|
||||
|
||||
constexpr identifier_rule_t identifier_rule{};
|
||||
|
||||
// arg_id ::= integer | identifier
|
||||
// integer ::= digit+
|
||||
// digit ::= "0"..."9"
|
||||
static constexpr auto arg_id_rule =
|
||||
grammar::variant_rule(
|
||||
identifier_rule,
|
||||
grammar::unsigned_rule<std::size_t>{});
|
||||
|
||||
struct format_spec_rule_t
|
||||
{
|
||||
using value_type = core::string_view;
|
||||
|
||||
system::result<value_type>
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const noexcept;
|
||||
};
|
||||
|
||||
constexpr format_spec_rule_t format_spec_rule{};
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
//
|
||||
// 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_DETAIL_SEGMENTS_ITER_IMPL_HPP
|
||||
#define BOOST_URL_DETAIL_SEGMENTS_ITER_IMPL_HPP
|
||||
|
||||
#include <boost/url/detail/parts_base.hpp>
|
||||
#include <boost/url/detail/url_impl.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
struct segments_iter_impl
|
||||
: private parts_base
|
||||
{
|
||||
path_ref ref;
|
||||
std::size_t pos = 0;
|
||||
std::size_t next = 0;
|
||||
std::size_t index = 0;
|
||||
std::size_t dn = 0;
|
||||
private:
|
||||
pct_string_view s_;
|
||||
public:
|
||||
|
||||
segments_iter_impl() = default;
|
||||
segments_iter_impl(
|
||||
segments_iter_impl const&) noexcept = default;
|
||||
segments_iter_impl& operator=(
|
||||
segments_iter_impl const&) noexcept = default;
|
||||
|
||||
// begin
|
||||
segments_iter_impl(
|
||||
detail::path_ref const&) noexcept;
|
||||
|
||||
// end
|
||||
segments_iter_impl(
|
||||
detail::path_ref const&,
|
||||
int) noexcept;
|
||||
|
||||
// at index
|
||||
segments_iter_impl(
|
||||
url_impl const& u_,
|
||||
std::size_t pos_,
|
||||
std::size_t i_) noexcept;
|
||||
|
||||
void update() noexcept;
|
||||
|
||||
BOOST_URL_DECL
|
||||
void
|
||||
increment() noexcept;
|
||||
|
||||
BOOST_URL_DECL
|
||||
void
|
||||
decrement() noexcept;
|
||||
|
||||
pct_string_view
|
||||
dereference() const noexcept
|
||||
{
|
||||
return s_;
|
||||
}
|
||||
|
||||
bool
|
||||
equal(
|
||||
segments_iter_impl const& other) const noexcept
|
||||
{
|
||||
BOOST_ASSERT(ref.alias_of(other.ref));
|
||||
return index == other.index;
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// 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_DETAIL_STRING_VIEW_HPP
|
||||
#define BOOST_URL_DETAIL_STRING_VIEW_HPP
|
||||
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
// We use detail::to_sv(s) instead of core::string_view(s) whenever
|
||||
// we should convert to core::string_view.
|
||||
// This is a workaround for GCC >=8.0 <8.4
|
||||
// See: https://github.com/boostorg/url/issues/672
|
||||
template<class T>
|
||||
core::string_view
|
||||
to_sv(T const& t) noexcept
|
||||
{
|
||||
return core::string_view(t);
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
//
|
||||
// Copyright (c) 2022 Vinnie Falco (vinnie.falco@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_DETAIL_URL_IMPL_HPP
|
||||
#define BOOST_URL_DETAIL_URL_IMPL_HPP
|
||||
|
||||
#include <boost/url/host_type.hpp>
|
||||
#include <boost/url/pct_string_view.hpp>
|
||||
#include <boost/url/scheme.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/url/detail/parts_base.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <cstdint>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
class url_view;
|
||||
class authority_view;
|
||||
|
||||
namespace detail {
|
||||
|
||||
constexpr char const* const empty_c_str_ = "";
|
||||
|
||||
// This is the private 'guts' of a
|
||||
// url_view, exposed so different parts
|
||||
// of the implementation can work on it.
|
||||
struct BOOST_URL_DECL url_impl : parts_base
|
||||
{
|
||||
static
|
||||
constexpr
|
||||
std::size_t const zero_ = 0;
|
||||
|
||||
// never nullptr
|
||||
char const* cs_ = empty_c_str_;
|
||||
|
||||
std::size_t offset_[id_end + 1] = {};
|
||||
std::size_t decoded_[id_end] = {};
|
||||
std::size_t nseg_ = 0;
|
||||
std::size_t nparam_ = 0;
|
||||
unsigned char ip_addr_[16] = {};
|
||||
// VFALCO don't we need a bool?
|
||||
std::uint16_t port_number_ = 0;
|
||||
host_type host_type_ =
|
||||
urls::host_type::none;
|
||||
scheme scheme_ =
|
||||
urls::scheme::none;
|
||||
|
||||
from from_ = from::string;
|
||||
|
||||
url_impl(
|
||||
from b) noexcept
|
||||
: from_(b)
|
||||
{
|
||||
}
|
||||
|
||||
// in url_view.ipp
|
||||
url_view construct() const noexcept;
|
||||
|
||||
// in authority_view.ipp
|
||||
authority_view
|
||||
construct_authority() const noexcept;
|
||||
|
||||
std::size_t len(int, int) const noexcept;
|
||||
std::size_t len(int) const noexcept;
|
||||
std::size_t offset(int) const noexcept;
|
||||
core::string_view get(int) const noexcept;
|
||||
core::string_view get(int, int) const noexcept;
|
||||
pct_string_view pct_get(int) const noexcept;
|
||||
pct_string_view pct_get(int, int) const noexcept;
|
||||
void set_size(int, std::size_t) noexcept;
|
||||
void split(int, std::size_t) noexcept;
|
||||
void adjust(int, int, std::size_t) noexcept;
|
||||
void collapse(int, int, std::size_t) noexcept;
|
||||
|
||||
void apply_scheme(core::string_view) noexcept;
|
||||
void apply_userinfo(pct_string_view const&,
|
||||
pct_string_view const*) noexcept;
|
||||
void apply_host(host_type, pct_string_view,
|
||||
unsigned char const*) noexcept;
|
||||
void apply_port(core::string_view, unsigned short) noexcept;
|
||||
void apply_authority(authority_view const&) noexcept;
|
||||
void apply_path(pct_string_view, std::size_t) noexcept;
|
||||
void apply_query(pct_string_view, std::size_t) noexcept;
|
||||
void apply_frag(pct_string_view) noexcept;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
// this allows a path to come from a
|
||||
// url_impl or a separate core::string_view
|
||||
class path_ref
|
||||
: private parts_base
|
||||
{
|
||||
url_impl const* impl_ = nullptr;
|
||||
char const* data_ = nullptr;
|
||||
std::size_t size_ = 0;
|
||||
std::size_t nseg_ = 0;
|
||||
std::size_t dn_ = 0;
|
||||
|
||||
public:
|
||||
path_ref() = default;
|
||||
path_ref(url_impl const& impl) noexcept;
|
||||
path_ref(core::string_view,
|
||||
std::size_t, std::size_t) noexcept;
|
||||
pct_string_view buffer() const noexcept;
|
||||
std::size_t size() const noexcept;
|
||||
char const* data() const noexcept;
|
||||
char const* end() const noexcept;
|
||||
std::size_t nseg() const noexcept;
|
||||
|
||||
bool
|
||||
alias_of(
|
||||
url_impl const& impl) const noexcept
|
||||
{
|
||||
return impl_ == &impl;
|
||||
}
|
||||
|
||||
bool
|
||||
alias_of(
|
||||
path_ref const& ref) const noexcept
|
||||
{
|
||||
if(impl_)
|
||||
return impl_ == ref.impl_;
|
||||
BOOST_ASSERT(data_ != ref.data_ || (
|
||||
size_ == ref.size_ &&
|
||||
nseg_ == ref.nseg_ &&
|
||||
dn_ == ref.dn_));
|
||||
return data_ == ref.data_;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
// this allows a params to come from a
|
||||
// url_impl or a separate core::string_view
|
||||
class BOOST_URL_DECL query_ref
|
||||
: private parts_base
|
||||
{
|
||||
url_impl const* impl_ = nullptr;
|
||||
char const* data_ = nullptr;
|
||||
std::size_t size_ = 0;
|
||||
std::size_t nparam_ = 0;
|
||||
std::size_t dn_ = 0;
|
||||
bool question_mark_ = false;
|
||||
|
||||
public:
|
||||
query_ref(
|
||||
core::string_view s, // buffer, no '?'
|
||||
std::size_t dn, // decoded size
|
||||
std::size_t nparam
|
||||
) noexcept;
|
||||
query_ref() = default;
|
||||
query_ref(url_impl const& impl) noexcept;
|
||||
pct_string_view buffer() const noexcept;
|
||||
std::size_t size() const noexcept; // with '?'
|
||||
char const* begin() const noexcept; // no '?'
|
||||
char const* end() const noexcept;
|
||||
std::size_t nparam() const noexcept;
|
||||
|
||||
bool
|
||||
alias_of(
|
||||
url_impl const& impl) const noexcept
|
||||
{
|
||||
return impl_ == &impl;
|
||||
}
|
||||
|
||||
bool
|
||||
alias_of(
|
||||
query_ref const& ref) const noexcept
|
||||
{
|
||||
if(impl_)
|
||||
return impl_ == ref.impl_;
|
||||
BOOST_ASSERT(data_ != ref.data_ || (
|
||||
size_ == ref.size_ &&
|
||||
nparam_ == ref.nparam_ &&
|
||||
dn_ == ref.dn_));
|
||||
return data_ == ref.data_;
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// 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_DETAIL_FORMAT_HPP
|
||||
#define BOOST_URL_DETAIL_FORMAT_HPP
|
||||
|
||||
#include <boost/url/detail/format_args.hpp>
|
||||
#include <boost/url/detail/pattern.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/url/url.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
inline
|
||||
void
|
||||
vformat_to(
|
||||
url_base& u,
|
||||
core::string_view fmt,
|
||||
detail::format_args args)
|
||||
{
|
||||
parse_pattern(fmt)
|
||||
.value().apply(u, args);
|
||||
}
|
||||
|
||||
inline
|
||||
url
|
||||
vformat(
|
||||
core::string_view fmt,
|
||||
detail::format_args args)
|
||||
{
|
||||
url u;
|
||||
vformat_to(u, fmt, args);
|
||||
return u;
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // url
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
//
|
||||
// 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_ENCODE_HPP
|
||||
#define BOOST_URL_ENCODE_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/encoding_opts.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/url/grammar/all_chars.hpp>
|
||||
#include <boost/url/grammar/string_token.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
/** Return the buffer size needed for percent-encoding
|
||||
|
||||
This function returns the exact number
|
||||
of bytes necessary to store the result
|
||||
of applying percent-encoding to the
|
||||
string using the given options and
|
||||
character set.
|
||||
No encoding is actually performed.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( encoded_size( "My Stuff", pchars ) == 10 );
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@return The number of bytes needed,
|
||||
excluding any null terminator.
|
||||
|
||||
@param s The string to measure.
|
||||
|
||||
@param unreserved The set of characters
|
||||
that is not percent-encoded.
|
||||
|
||||
@param opt The options for encoding. If
|
||||
this parameter is omitted, the default
|
||||
options are be used.
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-2.1"
|
||||
>2.1. Percent-Encoding (rfc3986)</a>
|
||||
|
||||
@see
|
||||
@ref encode,
|
||||
@ref encoding_opts,
|
||||
@ref make_pct_string_view.
|
||||
*/
|
||||
template<class CharSet>
|
||||
std::size_t
|
||||
encoded_size(
|
||||
core::string_view s,
|
||||
CharSet const& unreserved,
|
||||
encoding_opts opt = {}) noexcept;
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Apply percent-encoding to a string
|
||||
|
||||
This function applies percent-encoding
|
||||
to the string using the given options and
|
||||
character set. The destination buffer
|
||||
provided by the caller is used to store
|
||||
the result, which may be truncated if
|
||||
there is insufficient space.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
char buf[100];
|
||||
assert( encode( buf, sizeof(buf), "Program Files", pchars ) == 15 );
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@return The number of characters written
|
||||
to the destination buffer.
|
||||
|
||||
@param dest The destination buffer
|
||||
to write to.
|
||||
|
||||
@param size The number of writable
|
||||
characters pointed to by `dest`.
|
||||
If this is less than `encoded_size(s)`,
|
||||
the result is truncated.
|
||||
|
||||
@param s The string to encode.
|
||||
|
||||
@param unreserved The set of characters
|
||||
that is not percent-encoded.
|
||||
|
||||
@param opt The options for encoding. If
|
||||
this parameter is omitted, the default
|
||||
options are used.
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-2.1"
|
||||
>2.1. Percent-Encoding (rfc3986)</a>
|
||||
|
||||
@see
|
||||
@ref encode,
|
||||
@ref encoded_size,
|
||||
@ref make_pct_string_view.
|
||||
*/
|
||||
template<class CharSet>
|
||||
std::size_t
|
||||
encode(
|
||||
char* dest,
|
||||
std::size_t size,
|
||||
core::string_view s,
|
||||
CharSet const& unreserved,
|
||||
encoding_opts opt = {});
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
// VFALCO semi-private for now
|
||||
template<class CharSet>
|
||||
std::size_t
|
||||
encode_unsafe(
|
||||
char* dest,
|
||||
std::size_t size,
|
||||
core::string_view s,
|
||||
CharSet const& unreserved,
|
||||
encoding_opts opt);
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Return a percent-encoded string
|
||||
|
||||
This function applies percent-encoding
|
||||
to the string using the given options and
|
||||
character set, and returns the result as
|
||||
a string when called with default arguments.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
encoding_opts opt;
|
||||
opt.space_as_plus = true;
|
||||
std::string s = encode( "My Stuff", opt, pchars );
|
||||
|
||||
assert( s == "My+Stuff" );
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Calls to allocate may throw.
|
||||
|
||||
@return The string
|
||||
|
||||
@param s The string to encode.
|
||||
|
||||
@param unreserved The set of characters
|
||||
that is not percent-encoded.
|
||||
|
||||
@param opt The options for encoding. If
|
||||
this parameter is omitted, the default
|
||||
options are used.
|
||||
|
||||
@param token A string token.
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-2.1"
|
||||
>2.1. Percent-Encoding (rfc3986)</a>
|
||||
|
||||
@see
|
||||
@ref encode,
|
||||
@ref encoded_size,
|
||||
@ref encoding_opts,
|
||||
*/
|
||||
template<
|
||||
BOOST_URL_STRTOK_TPARAM,
|
||||
class CharSet>
|
||||
BOOST_URL_STRTOK_RETURN
|
||||
encode(
|
||||
core::string_view s,
|
||||
CharSet const& unreserved,
|
||||
encoding_opts opt = {},
|
||||
BOOST_URL_STRTOK_ARG(token)) noexcept;
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#include <boost/url/impl/encode.hpp>
|
||||
|
||||
#endif
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// 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_ENCODING_OPTS_HPP
|
||||
#define BOOST_URL_ENCODING_OPTS_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
/** Percent-encoding options
|
||||
|
||||
These options are used to customize
|
||||
the behavior of algorithms which use
|
||||
percent escapes, such as encoding
|
||||
or decoding.
|
||||
|
||||
@see
|
||||
@ref encode,
|
||||
@ref encoded_size,
|
||||
@ref pct_string_view.
|
||||
*/
|
||||
struct BOOST_URL_DECL encoding_opts
|
||||
{
|
||||
/** True if spaces encode to and from plus signs
|
||||
|
||||
This option controls whether or not
|
||||
the PLUS character ("+") is used to
|
||||
represent the SP character (" ") when
|
||||
encoding or decoding.
|
||||
Although not prescribed by the RFC, plus
|
||||
signs are commonly treated as spaces upon
|
||||
decoding when used in the query of URLs
|
||||
using well known schemes such as HTTP.
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1">
|
||||
application/x-www-form-urlencoded (w3.org)</a>
|
||||
*/
|
||||
bool space_as_plus = false;
|
||||
|
||||
/** True if hexadecimal digits are emitted as lower case
|
||||
|
||||
By default, percent-encoding algorithms
|
||||
emit hexadecimal digits A through F as
|
||||
uppercase letters. When this option is
|
||||
`true`, lowercase letters are used.
|
||||
*/
|
||||
bool lower_case = false;
|
||||
|
||||
/** True if nulls are not allowed
|
||||
|
||||
Normally all possible character values
|
||||
(from 0 to 255) are allowed, with reserved
|
||||
characters being replaced with escapes
|
||||
upon encoding. When this option is true,
|
||||
attempting to decode a null will result
|
||||
in an error.
|
||||
*/
|
||||
bool disallow_null = false;
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
encoding_opts(
|
||||
bool space_as_plus_ = false,
|
||||
bool lower_case_ = false,
|
||||
bool disallow_null_ = false) noexcept;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_ERROR_HPP
|
||||
#define BOOST_URL_ERROR_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
/** Error codes returned the library
|
||||
*/
|
||||
enum class error
|
||||
{
|
||||
// VFALCO 3 space indent or
|
||||
// else Doxygen malfunctions
|
||||
|
||||
/**
|
||||
* The operation completed successfully.
|
||||
*/
|
||||
success = 0,
|
||||
|
||||
/**
|
||||
* Null encountered in pct-encoded.
|
||||
*/
|
||||
illegal_null,
|
||||
|
||||
/**
|
||||
* Illegal reserved character in encoded string.
|
||||
*/
|
||||
illegal_reserved_char,
|
||||
|
||||
/**
|
||||
* A grammar element was not in canonical form.
|
||||
*/
|
||||
non_canonical,
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
/**
|
||||
* Bad hexadecimal digit.
|
||||
|
||||
This error condition is fatal.
|
||||
*/
|
||||
bad_pct_hexdig,
|
||||
|
||||
/**
|
||||
* The percent-encoded sequence is incomplete.
|
||||
|
||||
This error condition is fatal.
|
||||
*/
|
||||
incomplete_encoding,
|
||||
|
||||
/**
|
||||
* Missing hexadecimal digit.
|
||||
|
||||
This error condition is fatal.
|
||||
*/
|
||||
missing_pct_hexdig,
|
||||
|
||||
/**
|
||||
* No space in output buffer
|
||||
|
||||
This error is returned when a provided
|
||||
output buffer was too small to hold
|
||||
the complete result of an algorithm.
|
||||
*/
|
||||
no_space,
|
||||
|
||||
/**
|
||||
* The URL is not a base URL
|
||||
*/
|
||||
not_a_base
|
||||
};
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#include <boost/url/impl/error.hpp>
|
||||
|
||||
#endif
|
||||
+293
@@ -0,0 +1,293 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_ERROR_TYPES_HPP
|
||||
#define BOOST_URL_ERROR_TYPES_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/system/system_error.hpp>
|
||||
#include <boost/system/result.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
namespace error_types {
|
||||
#endif
|
||||
|
||||
/** The type of error category used by the library
|
||||
|
||||
@note This alias is no longer supported and
|
||||
should not be used in new code. Please use
|
||||
`system::error_category` instead.
|
||||
|
||||
This alias is included for backwards
|
||||
compatibility with earlier versions of the
|
||||
library.
|
||||
|
||||
However, it will be removed in future releases,
|
||||
and using it in new code is not recommended.
|
||||
|
||||
Please use the updated version instead to
|
||||
ensure compatibility with future versions of
|
||||
the library.
|
||||
|
||||
*/
|
||||
using error_category
|
||||
BOOST_URL_DEPRECATED("Use system::error_category instead") =
|
||||
boost::system::error_category;
|
||||
|
||||
/** The type of error code used by the library
|
||||
|
||||
@note This alias is no longer supported and
|
||||
should not be used in new code. Please use
|
||||
`system::error_code` instead.
|
||||
|
||||
This alias is included for backwards
|
||||
compatibility with earlier versions of the
|
||||
library.
|
||||
|
||||
However, it will be removed in future releases,
|
||||
and using it in new code is not recommended.
|
||||
|
||||
Please use the updated version instead to
|
||||
ensure compatibility with future versions of
|
||||
the library.
|
||||
|
||||
*/
|
||||
using error_code
|
||||
BOOST_URL_DEPRECATED("Use system::error_code instead") =
|
||||
boost::system::error_code;
|
||||
|
||||
/** The type of error condition used by the library
|
||||
|
||||
@note This alias is no longer supported and
|
||||
should not be used in new code. Please use
|
||||
`system::error_condition` instead.
|
||||
|
||||
This alias is included for backwards
|
||||
compatibility with earlier versions of the
|
||||
library.
|
||||
|
||||
However, it will be removed in future releases,
|
||||
and using it in new code is not recommended.
|
||||
|
||||
Please use the updated version instead to
|
||||
ensure compatibility with future versions of
|
||||
the library.
|
||||
|
||||
*/
|
||||
using error_condition
|
||||
BOOST_URL_DEPRECATED("Use system::error_condition instead") =
|
||||
boost::system::error_condition;
|
||||
|
||||
/** The type of system error thrown by the library
|
||||
|
||||
@note This alias is no longer supported and
|
||||
should not be used in new code. Please use
|
||||
`system::system_error` instead.
|
||||
|
||||
This alias is included for backwards
|
||||
compatibility with earlier versions of the
|
||||
library.
|
||||
|
||||
However, it will be removed in future releases,
|
||||
and using it in new code is not recommended.
|
||||
|
||||
Please use the updated version instead to
|
||||
ensure compatibility with future versions of
|
||||
the library.
|
||||
|
||||
*/
|
||||
using system_error
|
||||
BOOST_URL_DEPRECATED("Use system::system_error instead") =
|
||||
boost::system::system_error;
|
||||
|
||||
/** A function to return the generic error category used by the library
|
||||
|
||||
@note This alias is no longer supported and
|
||||
should not be used in new code. Please use
|
||||
`core::string_view` instead.
|
||||
|
||||
This alias is included for backwards
|
||||
compatibility with earlier versions of the
|
||||
library.
|
||||
|
||||
However, it will be removed in future releases,
|
||||
and using it in new code is not recommended.
|
||||
|
||||
Please use the updated version instead to
|
||||
ensure compatibility with future versions of
|
||||
the library.
|
||||
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
error_category const& generic_category();
|
||||
#else
|
||||
using boost::system::generic_category;
|
||||
#endif
|
||||
|
||||
/** A function to return the system error category used by the library
|
||||
|
||||
@note This alias is no longer supported and
|
||||
should not be used in new code. Please use
|
||||
`core::string_view` instead.
|
||||
|
||||
This alias is included for backwards
|
||||
compatibility with earlier versions of the
|
||||
library.
|
||||
|
||||
However, it will be removed in future releases,
|
||||
and using it in new code is not recommended.
|
||||
|
||||
Please use the updated version instead to
|
||||
ensure compatibility with future versions of
|
||||
the library.
|
||||
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
error_category const& system_category();
|
||||
#else
|
||||
using boost::system::system_category;
|
||||
#endif
|
||||
|
||||
/** The set of constants used for cross-platform error codes
|
||||
|
||||
@note This alias is no longer supported and
|
||||
should not be used in new code. Please use
|
||||
`core::string_view` instead.
|
||||
|
||||
This alias is included for backwards
|
||||
compatibility with earlier versions of the
|
||||
library.
|
||||
|
||||
However, it will be removed in future releases,
|
||||
and using it in new code is not recommended.
|
||||
|
||||
Please use the updated version instead to
|
||||
ensure compatibility with future versions of
|
||||
the library.
|
||||
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
enum errc
|
||||
{
|
||||
__see_below__
|
||||
};
|
||||
#else
|
||||
namespace errc = boost::system::errc;
|
||||
#endif
|
||||
|
||||
/** The type of result returned by library functions
|
||||
|
||||
@note This alias is no longer supported and
|
||||
should not be used in new code. Please use
|
||||
`system::result` instead.
|
||||
|
||||
This alias is included for backwards
|
||||
compatibility with earlier versions of the
|
||||
library.
|
||||
|
||||
However, it will be removed in future releases,
|
||||
and using it in new code is not recommended.
|
||||
|
||||
Please use the updated version instead to
|
||||
ensure compatibility with future versions of
|
||||
the library.
|
||||
|
||||
@details This is an alias template used as the return type
|
||||
for functions that can either return a container,
|
||||
or fail with an error code. This is a brief
|
||||
synopsis of the type:
|
||||
|
||||
@par Declaration
|
||||
@code
|
||||
template< class T >
|
||||
class result
|
||||
{
|
||||
public:
|
||||
//
|
||||
// Return true if the result contains an error
|
||||
//
|
||||
constexpr bool has_error() const noexcept;
|
||||
|
||||
//
|
||||
// Return the error
|
||||
//
|
||||
constexpr system::error_code error() const noexcept;
|
||||
|
||||
//
|
||||
// Return true if the result contains a value
|
||||
//
|
||||
constexpr bool has_value() const noexcept;
|
||||
constexpr explicit operator bool() const noexcept;
|
||||
|
||||
//
|
||||
// Return the value, or throw an exception
|
||||
//
|
||||
constexpr T& value();
|
||||
constexpr T const& value() const;
|
||||
|
||||
// Return the value.
|
||||
// Precondition: has_value()==true
|
||||
//
|
||||
constexpr T& operator*() noexcept;
|
||||
constexpr T* operator->() noexcept;
|
||||
constexpr T const& operator*() const noexcept;
|
||||
constexpr T const* operator->() const noexcept;
|
||||
|
||||
...more
|
||||
@endcode
|
||||
|
||||
@par Usage
|
||||
Given the function @ref parse_uri with this signature:
|
||||
@code
|
||||
system::result< url_view > parse_uri( core::string_view s ) noexcept;
|
||||
@endcode
|
||||
|
||||
The following statement captures the value in a
|
||||
variable upon success, otherwise throws:
|
||||
@code
|
||||
url_view u = parse_uri( "http://example.com/path/to/file.txt" ).value();
|
||||
@endcode
|
||||
|
||||
This statement captures the result in a local
|
||||
variable and inspects the error condition:
|
||||
@code
|
||||
system::result< url_view > rv = parse_uri( "http://example.com/path/to/file.txt" );
|
||||
|
||||
if(! rv )
|
||||
std::cout << rv.error();
|
||||
else
|
||||
std::cout << *rv;
|
||||
@endcode
|
||||
|
||||
@tparam T The type of value held by the result.
|
||||
|
||||
@see
|
||||
@li <a href="https://boost.org/libs/system/doc/html/system.html#ref_resultt_e"
|
||||
>`boost::system::result`</a>
|
||||
|
||||
*/
|
||||
template<class T>
|
||||
using result
|
||||
BOOST_URL_DEPRECATED("Use system::result<T> instead") =
|
||||
boost::system::result<T, system::error_code>;
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
} // error_types
|
||||
|
||||
using namespace error_types;
|
||||
#endif
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+416
@@ -0,0 +1,416 @@
|
||||
//
|
||||
// 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_FORMAT_HPP
|
||||
#define BOOST_URL_FORMAT_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/url/url.hpp>
|
||||
#include <boost/url/detail/vformat.hpp>
|
||||
#include <initializer_list>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
/** Format arguments into a URL
|
||||
|
||||
Format arguments according to the format
|
||||
URL string into a @ref url.
|
||||
|
||||
The rules for a format URL string are the same
|
||||
as for a `std::format_string`, where replacement
|
||||
fields are delimited by curly braces.
|
||||
|
||||
The URL components to which replacement fields
|
||||
belong are identified before replacement is
|
||||
applied and any invalid characters for that
|
||||
formatted argument are percent-escaped.
|
||||
|
||||
Hence, the delimiters between URL components,
|
||||
such as `:`, `//`, `?`, and `#`, should be
|
||||
included in the URL format string. Likewise,
|
||||
a format string with a single `"{}"` is
|
||||
interpreted as a path and any replacement
|
||||
characters invalid in this component will be
|
||||
encoded to form a valid URL.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert(format("{}", "Hello world!").buffer() == "Hello%20world%21");
|
||||
@endcode
|
||||
|
||||
@par Preconditions
|
||||
All replacement fields must be valid and the
|
||||
resulting URL should be valid after arguments
|
||||
are formatted into the URL.
|
||||
|
||||
Because any invalid characters for a URL
|
||||
component are encoded by this function, only
|
||||
replacements in the scheme and port components
|
||||
might be invalid, as these components do not
|
||||
allow percent-encoding of arbitrary
|
||||
characters.
|
||||
|
||||
@return A URL holding the formatted result.
|
||||
|
||||
@param fmt The format URL string.
|
||||
@param args Arguments to be formatted.
|
||||
|
||||
@throws system_error
|
||||
`fmt` contains an invalid format string and
|
||||
the result contains an invalid URL after
|
||||
replacements are applied.
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
replacement_field ::= "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
|
||||
arg_id ::= integer | identifier
|
||||
integer ::= digit+
|
||||
digit ::= "0"..."9"
|
||||
identifier ::= id_start id_continue*
|
||||
id_start ::= "a"..."z" | "A"..."Z" | "_"
|
||||
id_continue ::= id_start | digit
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://fmt.dev/latest/syntax.html"
|
||||
>Format String Syntax</a>
|
||||
|
||||
@see
|
||||
@ref format_to.
|
||||
|
||||
*/
|
||||
template <class... Args>
|
||||
url
|
||||
format(
|
||||
core::string_view fmt,
|
||||
Args&&... args)
|
||||
{
|
||||
return detail::vformat(
|
||||
fmt, detail::make_format_args(
|
||||
std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
/** Format arguments into a URL
|
||||
|
||||
Format arguments according to the format
|
||||
URL string into a @ref url_base.
|
||||
|
||||
The rules for a format URL string are the same
|
||||
as for a `std::format_string`, where replacement
|
||||
fields are delimited by curly braces.
|
||||
|
||||
The URL components to which replacement fields
|
||||
belong are identified before replacement is
|
||||
applied and any invalid characters for that
|
||||
formatted argument are percent-escaped.
|
||||
|
||||
Hence, the delimiters between URL components,
|
||||
such as `:`, `//`, `?`, and `#`, should be
|
||||
included in the URL format string. Likewise,
|
||||
a format string with a single `"{}"` is
|
||||
interpreted as a path and any replacement
|
||||
characters invalid in this component will be
|
||||
encoded to form a valid URL.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
static_url<30> u;
|
||||
format(u, "{}", "Hello world!");
|
||||
assert(u.buffer() == "Hello%20world%21");
|
||||
@endcode
|
||||
|
||||
@par Preconditions
|
||||
All replacement fields must be valid and the
|
||||
resulting URL should be valid after arguments
|
||||
are formatted into the URL.
|
||||
|
||||
Because any invalid characters for a URL
|
||||
component are encoded by this function, only
|
||||
replacements in the scheme and port components
|
||||
might be invalid, as these components do not
|
||||
allow percent-encoding of arbitrary
|
||||
characters.
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
|
||||
@param u An object that derives from @ref url_base.
|
||||
@param fmt The format URL string.
|
||||
@param args Arguments to be formatted.
|
||||
|
||||
@throws system_error
|
||||
`fmt` contains an invalid format string and
|
||||
`u` contains an invalid URL after replacements
|
||||
are applied.
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
replacement_field ::= "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
|
||||
arg_id ::= integer | identifier
|
||||
integer ::= digit+
|
||||
digit ::= "0"..."9"
|
||||
identifier ::= id_start id_continue*
|
||||
id_start ::= "a"..."z" | "A"..."Z" | "_"
|
||||
id_continue ::= id_start | digit
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://fmt.dev/latest/syntax.html"
|
||||
>Format String Syntax</a>
|
||||
|
||||
@see
|
||||
@ref format.
|
||||
|
||||
*/
|
||||
template <class... Args>
|
||||
void
|
||||
format_to(
|
||||
url_base& u,
|
||||
core::string_view fmt,
|
||||
Args&&... args)
|
||||
{
|
||||
detail::vformat_to(
|
||||
u, fmt, detail::make_format_args(
|
||||
std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
/** Format arguments into a URL
|
||||
|
||||
Format arguments according to the format
|
||||
URL string into a @ref url.
|
||||
|
||||
This overload allows type-erased arguments
|
||||
to be passed as an initializer_list, which
|
||||
is mostly convenient for named parameters.
|
||||
|
||||
All arguments must be convertible to a
|
||||
implementation defined type able to store a
|
||||
type-erased reference to any valid format
|
||||
argument.
|
||||
|
||||
The rules for a format URL string are the same
|
||||
as for a `std::format_string`, where replacement
|
||||
fields are delimited by curly braces.
|
||||
|
||||
The URL components to which replacement fields
|
||||
belong are identified before replacement is
|
||||
applied and any invalid characters for that
|
||||
formatted argument are percent-escaped.
|
||||
|
||||
Hence, the delimiters between URL components,
|
||||
such as `:`, `//`, `?`, and `#`, should be
|
||||
included in the URL format string. Likewise,
|
||||
a format string with a single `"{}"` is
|
||||
interpreted as a path and any replacement
|
||||
characters invalid in this component will be
|
||||
encoded to form a valid URL.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert(format("user/{id}", {{"id", 1}}).buffer() == "user/1");
|
||||
@endcode
|
||||
|
||||
@par Preconditions
|
||||
All replacement fields must be valid and the
|
||||
resulting URL should be valid after arguments
|
||||
are formatted into the URL.
|
||||
|
||||
Because any invalid characters for a URL
|
||||
component are encoded by this function, only
|
||||
replacements in the scheme and port components
|
||||
might be invalid, as these components do not
|
||||
allow percent-encoding of arbitrary
|
||||
characters.
|
||||
|
||||
@return A URL holding the formatted result.
|
||||
|
||||
@param fmt The format URL string.
|
||||
@param args Arguments to be formatted.
|
||||
|
||||
@throws system_error
|
||||
`fmt` contains an invalid format string and
|
||||
the result contains an invalid URL after
|
||||
replacements are applied.
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
replacement_field ::= "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
|
||||
arg_id ::= integer | identifier
|
||||
integer ::= digit+
|
||||
digit ::= "0"..."9"
|
||||
identifier ::= id_start id_continue*
|
||||
id_start ::= "a"..."z" | "A"..."Z" | "_"
|
||||
id_continue ::= id_start | digit
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://fmt.dev/latest/syntax.html"
|
||||
>Format String Syntax</a>
|
||||
|
||||
@see
|
||||
@ref format_to.
|
||||
|
||||
*/
|
||||
inline
|
||||
url
|
||||
format(
|
||||
core::string_view fmt,
|
||||
#ifdef BOOST_URL_DOCS
|
||||
std::initializer_list<__see_below__> args
|
||||
#else
|
||||
std::initializer_list<detail::format_arg> args
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return detail::vformat(
|
||||
fmt, detail::format_args(
|
||||
args.begin(), args.end()));
|
||||
}
|
||||
|
||||
/** Format arguments into a URL
|
||||
|
||||
Format arguments according to the format
|
||||
URL string into a @ref url_base.
|
||||
|
||||
This overload allows type-erased arguments
|
||||
to be passed as an initializer_list, which
|
||||
is mostly convenient for named parameters.
|
||||
|
||||
All arguments must be convertible to a
|
||||
implementation defined type able to store a
|
||||
type-erased reference to any valid format
|
||||
argument.
|
||||
|
||||
The rules for a format URL string are the same
|
||||
as for a `std::format_string`, where replacement
|
||||
fields are delimited by curly braces.
|
||||
|
||||
The URL components to which replacement fields
|
||||
belong are identified before replacement is
|
||||
applied and any invalid characters for that
|
||||
formatted argument are percent-escaped.
|
||||
|
||||
Hence, the delimiters between URL components,
|
||||
such as `:`, `//`, `?`, and `#`, should be
|
||||
included in the URL format string. Likewise,
|
||||
a format string with a single `"{}"` is
|
||||
interpreted as a path and any replacement
|
||||
characters invalid in this component will be
|
||||
encoded to form a valid URL.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
static_url<30> u;
|
||||
format_to(u, "user/{id}", {{"id", 1}})
|
||||
assert(u.buffer() == "user/1");
|
||||
@endcode
|
||||
|
||||
@par Preconditions
|
||||
All replacement fields must be valid and the
|
||||
resulting URL should be valid after arguments
|
||||
are formatted into the URL.
|
||||
|
||||
Because any invalid characters for a URL
|
||||
component are encoded by this function, only
|
||||
replacements in the scheme and port components
|
||||
might be invalid, as these components do not
|
||||
allow percent-encoding of arbitrary
|
||||
characters.
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
|
||||
@param u An object that derives from @ref url_base.
|
||||
@param fmt The format URL string.
|
||||
@param args Arguments to be formatted.
|
||||
|
||||
@throws system_error
|
||||
`fmt` contains an invalid format string and
|
||||
`u` contains an invalid URL after replacements
|
||||
are applied.
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
replacement_field ::= "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
|
||||
arg_id ::= integer | identifier
|
||||
integer ::= digit+
|
||||
digit ::= "0"..."9"
|
||||
identifier ::= id_start id_continue*
|
||||
id_start ::= "a"..."z" | "A"..."Z" | "_"
|
||||
id_continue ::= id_start | digit
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://fmt.dev/latest/syntax.html"
|
||||
>Format String Syntax</a>
|
||||
|
||||
@see
|
||||
@ref format.
|
||||
|
||||
*/
|
||||
inline
|
||||
void
|
||||
format_to(
|
||||
url_base& u,
|
||||
core::string_view fmt,
|
||||
#ifdef BOOST_URL_DOCS
|
||||
std::initializer_list<__see_below__> args
|
||||
#else
|
||||
std::initializer_list<detail::format_arg> args
|
||||
#endif
|
||||
)
|
||||
{
|
||||
detail::vformat_to(
|
||||
u, fmt, detail::format_args(
|
||||
args.begin(), args.end()));
|
||||
}
|
||||
|
||||
/** Designate a named argument for a replacement field
|
||||
|
||||
Construct a named argument for a format URL
|
||||
string that contains named replacement fields.
|
||||
|
||||
The function parameters should be convertible
|
||||
to an implementation defined type able to
|
||||
store the name and a reference to any type
|
||||
potentially used as a format argument.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert(format("user/{id}", arg("id", 1)).buffer() == "user/1");
|
||||
@endcode
|
||||
|
||||
@return An temporary object with reference
|
||||
semantics for a named argument
|
||||
|
||||
@param name The argument name
|
||||
@param arg The argument value
|
||||
|
||||
@see
|
||||
@ref format,
|
||||
@ref format_to.
|
||||
|
||||
*/
|
||||
template <class T>
|
||||
#ifdef BOOST_URL_DOCS
|
||||
__implementation_defined__
|
||||
#else
|
||||
detail::named_arg<T>
|
||||
#endif
|
||||
arg(core::string_view name, T const& arg)
|
||||
{
|
||||
return {name, arg};
|
||||
}
|
||||
|
||||
} // url
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_GRAMMAR_HPP
|
||||
#define BOOST_URL_GRAMMAR_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
|
||||
#include <boost/url/grammar/alnum_chars.hpp>
|
||||
#include <boost/url/grammar/alpha_chars.hpp>
|
||||
#include <boost/url/grammar/charset.hpp>
|
||||
#include <boost/url/grammar/ci_string.hpp>
|
||||
#include <boost/url/grammar/dec_octet_rule.hpp>
|
||||
#include <boost/url/grammar/delim_rule.hpp>
|
||||
#include <boost/url/grammar/digit_chars.hpp>
|
||||
#include <boost/url/grammar/error.hpp>
|
||||
#include <boost/url/grammar/hexdig_chars.hpp>
|
||||
#include <boost/url/grammar/literal_rule.hpp>
|
||||
#include <boost/url/grammar/lut_chars.hpp>
|
||||
#include <boost/url/grammar/not_empty_rule.hpp>
|
||||
#include <boost/url/grammar/optional_rule.hpp>
|
||||
#include <boost/url/grammar/parse.hpp>
|
||||
#include <boost/url/grammar/range_rule.hpp>
|
||||
#include <boost/url/grammar/recycled.hpp>
|
||||
#include <boost/url/grammar/string_token.hpp>
|
||||
#include <boost/url/grammar/string_view_base.hpp>
|
||||
#include <boost/url/grammar/token_rule.hpp>
|
||||
#include <boost/url/grammar/tuple_rule.hpp>
|
||||
#include <boost/url/grammar/type_traits.hpp>
|
||||
#include <boost/url/grammar/unsigned_rule.hpp>
|
||||
#include <boost/url/grammar/variant_rule.hpp>
|
||||
#include <boost/url/grammar/vchars.hpp>
|
||||
|
||||
#endif
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
//
|
||||
// Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_ALL_CHARS_HPP
|
||||
#define BOOST_URL_GRAMMAR_ALL_CHARS_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/grammar/detail/charset.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** The set of all characters
|
||||
|
||||
@par Example
|
||||
Character sets are used with rules and the
|
||||
functions @ref find_if and @ref find_if_not.
|
||||
@code
|
||||
system::result< core::string_view > rv = parse( "JohnDoe", token_rule( all_chars ) );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
ALL = %x00-FF
|
||||
@endcode
|
||||
|
||||
@see
|
||||
@ref find_if,
|
||||
@ref find_if_not,
|
||||
@ref parse,
|
||||
@ref token_rule.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
constexpr __implementation_defined__ all_chars;
|
||||
#else
|
||||
struct all_chars_t
|
||||
{
|
||||
constexpr
|
||||
all_chars_t() noexcept = default;
|
||||
|
||||
constexpr
|
||||
bool
|
||||
operator()(char) const noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef BOOST_URL_USE_SSE2
|
||||
char const*
|
||||
find_if(
|
||||
char const* first,
|
||||
char const* last) const noexcept
|
||||
{
|
||||
return detail::find_if_pred(
|
||||
*this, first, last);
|
||||
}
|
||||
|
||||
char const*
|
||||
find_if_not(
|
||||
char const* first,
|
||||
char const* last) const noexcept
|
||||
{
|
||||
return detail::find_if_not_pred(
|
||||
*this, first, last);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
/** A character set containing all characters.
|
||||
|
||||
@see
|
||||
@ref all_chars_t
|
||||
*/
|
||||
constexpr all_chars_t all_chars{};
|
||||
#endif
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_ALNUM_CHARS_HPP
|
||||
#define BOOST_URL_GRAMMAR_ALNUM_CHARS_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/grammar/detail/charset.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** The set of letters and digits
|
||||
|
||||
@par Example
|
||||
Character sets are used with rules and the
|
||||
functions @ref find_if and @ref find_if_not.
|
||||
@code
|
||||
system::result< core::string_view > = parse( "Johnny42", token_rule( alnumchars ) );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
ALNUM = ALPHA / DIGIT
|
||||
|
||||
ALPHA = %x41-5A / %x61-7A
|
||||
; A-Z / a-z
|
||||
|
||||
DIGIT = %x30-39
|
||||
; 0-9
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc5234#appendix-B.1"
|
||||
>B.1. Core Rules (rfc5234)</a>
|
||||
|
||||
@see
|
||||
@ref find_if,
|
||||
@ref find_if_not,
|
||||
@ref parse,
|
||||
@ref token_rule.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
constexpr __implementation_defined__ alnum_chars;
|
||||
#else
|
||||
struct alnum_chars_t
|
||||
{
|
||||
constexpr
|
||||
bool
|
||||
operator()(char c) const noexcept
|
||||
{
|
||||
return
|
||||
(c >= '0' && c <= '9') ||
|
||||
(c >= 'A' && c <= 'Z') ||
|
||||
(c >= 'a' && c <= 'z');
|
||||
}
|
||||
|
||||
#ifdef BOOST_URL_USE_SSE2
|
||||
char const*
|
||||
find_if(
|
||||
char const* first,
|
||||
char const* last) const noexcept
|
||||
{
|
||||
return detail::find_if_pred(
|
||||
*this, first, last);
|
||||
}
|
||||
|
||||
char const*
|
||||
find_if_not(
|
||||
char const* first,
|
||||
char const* last) const noexcept
|
||||
{
|
||||
return detail::find_if_not_pred(
|
||||
*this, first, last);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
constexpr alnum_chars_t alnum_chars{};
|
||||
#endif
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
//
|
||||
// Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_ALPHA_CHARS_HPP
|
||||
#define BOOST_URL_GRAMMAR_ALPHA_CHARS_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/grammar/detail/charset.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** The set of all letters
|
||||
|
||||
@par Example
|
||||
Character sets are used with rules and the
|
||||
functions @ref find_if and @ref find_if_not.
|
||||
@code
|
||||
system::result< core::string_view > rv = parse( "JohnDoe", token_rule( alpha_chars ) );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
ALPHA = %x41-5A / %x61-7A
|
||||
; A-Z / a-z
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc5234#appendix-B.1"
|
||||
>B.1. Core Rules (rfc5234)</a>
|
||||
|
||||
@see
|
||||
@ref find_if,
|
||||
@ref find_if_not,
|
||||
@ref parse,
|
||||
@ref token_rule.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
constexpr __implementation_defined__ alpha_chars;
|
||||
#else
|
||||
struct alpha_chars_t
|
||||
{
|
||||
constexpr
|
||||
alpha_chars_t() noexcept = default;
|
||||
|
||||
constexpr
|
||||
bool
|
||||
operator()(char c) const noexcept
|
||||
{
|
||||
return
|
||||
(c >= 'A' && c <= 'Z') ||
|
||||
(c >= 'a' && c <= 'z');
|
||||
}
|
||||
|
||||
#ifdef BOOST_URL_USE_SSE2
|
||||
char const*
|
||||
find_if(
|
||||
char const* first,
|
||||
char const* last) const noexcept
|
||||
{
|
||||
return detail::find_if_pred(
|
||||
*this, first, last);
|
||||
}
|
||||
|
||||
char const*
|
||||
find_if_not(
|
||||
char const* first,
|
||||
char const* last) const noexcept
|
||||
{
|
||||
return detail::find_if_not_pred(
|
||||
*this, first, last);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
/** A character set containing the alphabetical characters.
|
||||
|
||||
@see
|
||||
@ref alpha_chars_t
|
||||
*/
|
||||
constexpr alpha_chars_t alpha_chars{};
|
||||
#endif
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
//
|
||||
// Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_CHARSET_HPP
|
||||
#define BOOST_URL_GRAMMAR_CHARSET_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/grammar/detail/charset.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** Alias for `std::true_type` if T satisfies <em>CharSet</em>.
|
||||
|
||||
This metafunction determines if the
|
||||
type `T` meets these requirements of
|
||||
<em>CharSet</em>:
|
||||
|
||||
@li An instance of `T` is invocable
|
||||
with this equivalent function signature:
|
||||
@code
|
||||
bool T::operator()( char ) const noexcept;
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
Use with `enable_if` on the return value:
|
||||
@code
|
||||
template< class CharSet >
|
||||
typename std::enable_if< is_charset<T>::value >::type
|
||||
func( CharSet const& cs );
|
||||
@endcode
|
||||
|
||||
@tparam T the type to check.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<class T>
|
||||
using is_charset = __see_below__;
|
||||
#else
|
||||
template<class T, class = void>
|
||||
struct is_charset : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_charset<T, void_t<
|
||||
decltype(
|
||||
std::declval<bool&>() =
|
||||
std::declval<T const&>().operator()(
|
||||
std::declval<char>())
|
||||
) > > : std::true_type
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Find the first character in the string that is in the set.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@return A pointer to the found character,
|
||||
otherwise the value `last`.
|
||||
|
||||
@param first A pointer to the first character
|
||||
in the string to search.
|
||||
|
||||
@param last A pointer to one past the last
|
||||
character in the string to search.
|
||||
|
||||
@param cs The character set to use.
|
||||
|
||||
@see
|
||||
@ref find_if_not.
|
||||
*/
|
||||
template<class CharSet>
|
||||
char const*
|
||||
find_if(
|
||||
char const* const first,
|
||||
char const* const last,
|
||||
CharSet const& cs) noexcept
|
||||
{
|
||||
// If you get a compile error here
|
||||
// it means your type does not meet
|
||||
// the requirements. Please check the
|
||||
// documentation.
|
||||
static_assert(
|
||||
is_charset<CharSet>::value,
|
||||
"CharSet requirements not met");
|
||||
|
||||
return detail::find_if(first, last, cs,
|
||||
detail::has_find_if<CharSet>{});
|
||||
}
|
||||
|
||||
/** Find the first character in the string that is not in CharSet
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@return A pointer to the found character,
|
||||
otherwise the value `last`.
|
||||
|
||||
@param first A pointer to the first character
|
||||
in the string to search.
|
||||
|
||||
@param last A pointer to one past the last
|
||||
character in the string to search.
|
||||
|
||||
@param cs The character set to use.
|
||||
|
||||
@see
|
||||
@ref find_if_not.
|
||||
*/
|
||||
template<class CharSet>
|
||||
char const*
|
||||
find_if_not(
|
||||
char const* const first,
|
||||
char const* const last,
|
||||
CharSet const& cs) noexcept
|
||||
{
|
||||
// If you get a compile error here
|
||||
// it means your type does not meet
|
||||
// the requirements. Please check the
|
||||
// documentation.
|
||||
static_assert(
|
||||
is_charset<CharSet>::value,
|
||||
"CharSet requirements not met");
|
||||
|
||||
return detail::find_if_not(first, last, cs,
|
||||
detail::has_find_if_not<CharSet>{});
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
namespace detail {
|
||||
|
||||
template<class CharSet>
|
||||
struct charset_ref
|
||||
{
|
||||
CharSet const& cs_;
|
||||
|
||||
constexpr
|
||||
bool
|
||||
operator()(char ch) const noexcept
|
||||
{
|
||||
return cs_(ch);
|
||||
}
|
||||
|
||||
char const*
|
||||
find_if(
|
||||
char const* first,
|
||||
char const* last) const noexcept
|
||||
{
|
||||
return grammar::find_if(
|
||||
first, last, cs_);
|
||||
}
|
||||
|
||||
char const*
|
||||
find_if_not(
|
||||
char const* first,
|
||||
char const* last) const noexcept
|
||||
{
|
||||
return grammar::find_if_not(
|
||||
first, last, cs_ );
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
#endif
|
||||
|
||||
/** Return a reference to a character set
|
||||
|
||||
This function returns a character set which
|
||||
references the specified object. This is
|
||||
used to reduce the number of bytes of
|
||||
storage (`sizeof`) required by a combinator
|
||||
when it stores a copy of the object.
|
||||
<br>
|
||||
Ownership of the object is not transferred;
|
||||
the caller is responsible for ensuring the
|
||||
lifetime of the object is extended until it
|
||||
is no longer referenced. For best results,
|
||||
`ref` should only be used with compile-time
|
||||
constants.
|
||||
*/
|
||||
template<class CharSet>
|
||||
constexpr
|
||||
#ifdef BOOST_URL_DOCS
|
||||
__implementation_defined__
|
||||
#else
|
||||
typename std::enable_if<
|
||||
is_charset<CharSet>::value &&
|
||||
! std::is_same<CharSet,
|
||||
detail::charset_ref<CharSet> >::value,
|
||||
detail::charset_ref<CharSet> >::type
|
||||
#endif
|
||||
ref(CharSet const& cs) noexcept
|
||||
{
|
||||
return detail::charset_ref<
|
||||
CharSet>{cs};
|
||||
}
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+356
@@ -0,0 +1,356 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_CI_STRING_HPP
|
||||
#define BOOST_URL_GRAMMAR_CI_STRING_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/url/grammar/detail/ci_string.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
// Algorithms for interacting with low-ASCII
|
||||
// characters and strings, for implementing
|
||||
// semantics in RFCs. These routines do not
|
||||
// use std::locale.
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Return c converted to lowercase
|
||||
|
||||
This function returns the character,
|
||||
converting it to lowercase if it is
|
||||
uppercase.
|
||||
The function is defined only for
|
||||
low-ASCII characters.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( to_lower( 'A' ) == 'a' );
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@return The converted character
|
||||
|
||||
@param c The character to convert
|
||||
|
||||
@see
|
||||
@ref to_upper.
|
||||
*/
|
||||
constexpr
|
||||
char
|
||||
to_lower(char c) noexcept
|
||||
{
|
||||
return detail::to_lower(c);
|
||||
}
|
||||
|
||||
/** Return c converted to uppercase
|
||||
|
||||
This function returns the character,
|
||||
converting it to uppercase if it is
|
||||
lowercase.
|
||||
The function is defined only for
|
||||
low-ASCII characters.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( to_upper( 'a' ) == 'A' );
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@return The converted character
|
||||
|
||||
@param c The character to convert
|
||||
|
||||
@see
|
||||
@ref to_lower.
|
||||
*/
|
||||
constexpr
|
||||
char
|
||||
to_upper(char c) noexcept
|
||||
{
|
||||
return detail::to_upper(c);
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Return the case-insensitive comparison of s0 and s1
|
||||
|
||||
This returns the lexicographical comparison
|
||||
of two strings, ignoring case.
|
||||
The function is defined only for strings
|
||||
containing low-ASCII characters.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( ci_compare( "boost", "Boost" ) == 0 );
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@return 0 if the strings are equal, -1 if
|
||||
`s0` is less than `s1`, or 1 if `s0` is
|
||||
greater than s1.
|
||||
|
||||
@param s0 The first string
|
||||
|
||||
@param s1 The second string
|
||||
|
||||
@see
|
||||
@ref ci_is_equal,
|
||||
@ref ci_is_less.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
int
|
||||
ci_compare(
|
||||
core::string_view s0,
|
||||
core::string_view s1) noexcept;
|
||||
|
||||
/** Return the case-insensitive digest of a string
|
||||
|
||||
The hash function is non-cryptographic and
|
||||
not hardened against algorithmic complexity
|
||||
attacks.
|
||||
Returned digests are suitable for usage in
|
||||
unordered containers.
|
||||
The function is defined only for strings
|
||||
containing low-ASCII characters.
|
||||
|
||||
@return The digest
|
||||
|
||||
@param s The string
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
std::size_t
|
||||
ci_digest(
|
||||
core::string_view s) noexcept;
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Return true if s0 equals s1 using case-insensitive comparison
|
||||
|
||||
The function is defined only for strings
|
||||
containing low-ASCII characters.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( ci_is_equal( "Boost", "boost" ) );
|
||||
@endcode
|
||||
|
||||
@see
|
||||
@ref ci_compare,
|
||||
@ref ci_is_less.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<
|
||||
class String0,
|
||||
class String1>
|
||||
bool
|
||||
ci_is_equal(
|
||||
String0 const& s0,
|
||||
String1 const& s1);
|
||||
#else
|
||||
|
||||
template<
|
||||
class String0,
|
||||
class String1>
|
||||
auto
|
||||
ci_is_equal(
|
||||
String0 const& s0,
|
||||
String1 const& s1) ->
|
||||
typename std::enable_if<
|
||||
! std::is_convertible<
|
||||
String0, core::string_view>::value ||
|
||||
! std::is_convertible<
|
||||
String1, core::string_view>::value,
|
||||
bool>::type
|
||||
{
|
||||
// this overload supports forward iterators and
|
||||
// does not assume the existence core::string_view::size
|
||||
if( detail::type_id<String0>() >
|
||||
detail::type_id<String1>())
|
||||
return detail::ci_is_equal(s1, s0);
|
||||
return detail::ci_is_equal(s0, s1);
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
ci_is_equal(
|
||||
core::string_view s0,
|
||||
core::string_view s1) noexcept
|
||||
{
|
||||
// this overload is faster as it makes use of
|
||||
// core::string_view::size
|
||||
if(s0.size() != s1.size())
|
||||
return false;
|
||||
return detail::ci_is_equal(s0, s1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Return true if s0 is less than s1 using case-insensitive comparison
|
||||
|
||||
The comparison algorithm implements a
|
||||
case-insensitive total order on the set
|
||||
of all strings; however, it is not a
|
||||
lexicographical comparison.
|
||||
The function is defined only for strings
|
||||
containing low-ASCII characters.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( ! ci_is_less( "Boost", "boost" ) );
|
||||
@endcode
|
||||
|
||||
@see
|
||||
@ref ci_compare,
|
||||
@ref ci_is_equal.
|
||||
*/
|
||||
inline
|
||||
bool
|
||||
ci_is_less(
|
||||
core::string_view s0,
|
||||
core::string_view s1) noexcept
|
||||
{
|
||||
if(s0.size() != s1.size())
|
||||
return s0.size() < s1.size();
|
||||
return detail::ci_is_less(s0, s1);
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** A case-insensitive hash function object for strings
|
||||
|
||||
The hash function is non-cryptographic and
|
||||
not hardened against algorithmic complexity
|
||||
attacks.
|
||||
This is a suitable hash function for
|
||||
unordered containers.
|
||||
The function is defined only for strings
|
||||
containing low-ASCII characters.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
boost::unordered_map< std::string, std::string, ci_hash, ci_equal > m1;
|
||||
|
||||
std::unordered_map < std::string, std::string, ci_hash, ci_equal > m2; // (since C++20)
|
||||
@endcode
|
||||
|
||||
@see
|
||||
@ref ci_equal,
|
||||
@ref ci_less.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
using ci_hash = __see_below__;
|
||||
#else
|
||||
struct ci_hash
|
||||
{
|
||||
using is_transparent = void;
|
||||
|
||||
std::size_t
|
||||
operator()(
|
||||
core::string_view s) const noexcept
|
||||
{
|
||||
return ci_digest(s);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/** A case-insensitive equals predicate for strings
|
||||
|
||||
The function object returns `true` when
|
||||
two strings are equal, ignoring case.
|
||||
This is a suitable equality predicate for
|
||||
unordered containers.
|
||||
The function is defined only for strings
|
||||
containing low-ASCII characters.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
boost::unordered_map< std::string, std::string, ci_hash, ci_equal > m1;
|
||||
|
||||
std::unordered_map < std::string, std::string, ci_hash, ci_equal > m2; // (since C++20)
|
||||
@endcode
|
||||
|
||||
@see
|
||||
@ref ci_hash,
|
||||
@ref ci_less.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
using ci_equal = __see_below__;
|
||||
#else
|
||||
struct ci_equal
|
||||
{
|
||||
using is_transparent = void;
|
||||
|
||||
template<
|
||||
class String0, class String1>
|
||||
bool
|
||||
operator()(
|
||||
String0 s0,
|
||||
String1 s1) const noexcept
|
||||
{
|
||||
return ci_is_equal(s0, s1);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/** A case-insensitive less predicate for strings
|
||||
|
||||
The comparison algorithm implements a
|
||||
case-insensitive total order on the set
|
||||
of all ASCII strings; however, it is
|
||||
not a lexicographical comparison.
|
||||
This is a suitable predicate for
|
||||
ordered containers.
|
||||
The function is defined only for strings
|
||||
containing low-ASCII characters.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
boost::container::map< std::string, std::string, ci_less > m1;
|
||||
|
||||
std::map< std::string, std::string, ci_less > m2; // (since C++14)
|
||||
@endcode
|
||||
|
||||
@see
|
||||
@ref ci_equal,
|
||||
@ref ci_hash.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
using ci_less = __see_below__;
|
||||
#else
|
||||
struct ci_less
|
||||
{
|
||||
using is_transparent = void;
|
||||
|
||||
std::size_t
|
||||
operator()(
|
||||
core::string_view s0,
|
||||
core::string_view s1) const noexcept
|
||||
{
|
||||
return ci_is_less(s0, s1);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_DEC_OCTET_RULE_HPP
|
||||
#define BOOST_URL_GRAMMAR_DEC_OCTET_RULE_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** Match a decimal octet
|
||||
|
||||
A decimal octet is precise way of
|
||||
saying a number from 0 to 255. These
|
||||
are commonly used in IPv4 addresses.
|
||||
|
||||
@par Value Type
|
||||
@code
|
||||
using value_type = unsigned char;
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
Rules are used with the function @ref parse.
|
||||
@code
|
||||
system::result< unsigned char > rv = parse( "255", dec_octet_rule );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
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 <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
|
||||
>3.2.2. Host (rfc3986)</a>
|
||||
|
||||
@see
|
||||
@ref parse.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
constexpr __implementation_defined__ dec_octet_rule;
|
||||
#else
|
||||
struct dec_octet_rule_t
|
||||
{
|
||||
using value_type = unsigned char;
|
||||
|
||||
BOOST_URL_DECL
|
||||
auto
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end
|
||||
) const noexcept ->
|
||||
system::result<value_type>;
|
||||
};
|
||||
|
||||
constexpr dec_octet_rule_t dec_octet_rule{};
|
||||
#endif
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_DELIM_RULE_HPP
|
||||
#define BOOST_URL_GRAMMAR_DELIM_RULE_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/url/grammar/charset.hpp>
|
||||
#include <boost/url/grammar/error.hpp>
|
||||
#include <boost/url/grammar/type_traits.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** Match a character literal
|
||||
|
||||
This matches the specified character.
|
||||
The value is a reference to the character
|
||||
in the underlying buffer, expressed as a
|
||||
`core::string_view`. The function @ref squelch
|
||||
may be used to turn this into `void` instead.
|
||||
If there is no more input, the error code
|
||||
@ref error::need_more is returned.
|
||||
|
||||
@par Value Type
|
||||
@code
|
||||
using value_type = core::string_view;
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
Rules are used with the function @ref parse.
|
||||
@code
|
||||
system::result< core::string_view > rv = parse( ".", delim_rule('.') );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
char = %00-FF
|
||||
@endcode
|
||||
|
||||
@param ch The character to match
|
||||
|
||||
@see
|
||||
@ref parse,
|
||||
@ref squelch.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
constexpr
|
||||
__implementation_defined__
|
||||
delim_rule( char ch ) noexcept;
|
||||
#else
|
||||
struct ch_delim_rule
|
||||
{
|
||||
using value_type = core::string_view;
|
||||
|
||||
constexpr
|
||||
ch_delim_rule(char ch) noexcept
|
||||
: ch_(ch)
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_URL_DECL
|
||||
system::result<value_type>
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const noexcept;
|
||||
|
||||
private:
|
||||
char ch_;
|
||||
};
|
||||
|
||||
constexpr
|
||||
ch_delim_rule
|
||||
delim_rule( char ch ) noexcept
|
||||
{
|
||||
return ch_delim_rule(ch);
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Match a single character from a character set
|
||||
|
||||
This matches exactly one character which
|
||||
belongs to the specified character set.
|
||||
The value is a reference to the character
|
||||
in the underlying buffer, expressed as a
|
||||
`core::string_view`. The function @ref squelch
|
||||
may be used to turn this into `void` instead.
|
||||
If there is no more input, the error code
|
||||
@ref error::need_more is returned.
|
||||
|
||||
@par Value Type
|
||||
@code
|
||||
using value_type = core::string_view;
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
Rules are used with the function @ref parse.
|
||||
@code
|
||||
system::result< core::string_view > rv = parse( "X", delim_rule( alpha_chars ) );
|
||||
@endcode
|
||||
|
||||
@param cs The character set to use.
|
||||
|
||||
@see
|
||||
@ref alpha_chars,
|
||||
@ref parse,
|
||||
@ref squelch.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<class CharSet>
|
||||
constexpr
|
||||
__implementation_defined__
|
||||
delim_rule( CharSet const& cs ) noexcept;
|
||||
#else
|
||||
template<class CharSet>
|
||||
struct cs_delim_rule
|
||||
{
|
||||
using value_type = core::string_view;
|
||||
|
||||
constexpr
|
||||
cs_delim_rule(
|
||||
CharSet const& cs) noexcept
|
||||
: cs_(cs)
|
||||
{
|
||||
}
|
||||
|
||||
system::result<value_type>
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const noexcept
|
||||
{
|
||||
if(it == end)
|
||||
{
|
||||
// end
|
||||
BOOST_URL_RETURN_EC(
|
||||
error::need_more);
|
||||
}
|
||||
if(! cs_(*it))
|
||||
{
|
||||
// wrong character
|
||||
BOOST_URL_RETURN_EC(
|
||||
error::mismatch);
|
||||
}
|
||||
return core::string_view{
|
||||
it++, 1 };
|
||||
}
|
||||
|
||||
private:
|
||||
CharSet cs_;
|
||||
};
|
||||
|
||||
template<class CharSet>
|
||||
constexpr
|
||||
typename std::enable_if<
|
||||
! std::is_convertible<
|
||||
CharSet, char>::value,
|
||||
cs_delim_rule<CharSet>>::type
|
||||
delim_rule(
|
||||
CharSet const& cs) noexcept
|
||||
{
|
||||
// If you get a compile error here it
|
||||
// means that your type does not meet
|
||||
// the requirements for a CharSet.
|
||||
// Please consult the documentation.
|
||||
static_assert(
|
||||
is_charset<CharSet>::value,
|
||||
"CharSet requirements not met");
|
||||
|
||||
return cs_delim_rule<CharSet>(cs);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_DETAIL_CHARSET_HPP
|
||||
#define BOOST_URL_GRAMMAR_DETAIL_CHARSET_HPP
|
||||
|
||||
#include <boost/core/bit.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
#ifdef BOOST_URL_USE_SSE2
|
||||
# include <emmintrin.h>
|
||||
# include <xmmintrin.h>
|
||||
# ifdef _MSC_VER
|
||||
# include <intrin.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
namespace detail {
|
||||
|
||||
template<class T, class = void>
|
||||
struct has_find_if : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct has_find_if<T, void_t<
|
||||
decltype(
|
||||
std::declval<char const*&>() =
|
||||
std::declval<T const&>().find_if(
|
||||
std::declval<char const*>(),
|
||||
std::declval<char const*>())
|
||||
)>> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class T, class = void>
|
||||
struct has_find_if_not : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct has_find_if_not<T, void_t<
|
||||
decltype(
|
||||
std::declval<char const*&>() =
|
||||
std::declval<T const&>().find_if_not(
|
||||
std::declval<char const*>(),
|
||||
std::declval<char const*>())
|
||||
)>> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class Pred>
|
||||
char const*
|
||||
find_if(
|
||||
char const* first,
|
||||
char const* const last,
|
||||
Pred const& pred,
|
||||
std::false_type) noexcept
|
||||
{
|
||||
while(first != last)
|
||||
{
|
||||
if(pred(*first))
|
||||
break;
|
||||
++first;
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
template<class Pred>
|
||||
char const*
|
||||
find_if(
|
||||
char const* first,
|
||||
char const* const last,
|
||||
Pred const& pred,
|
||||
std::true_type) noexcept
|
||||
{
|
||||
return pred.find_if(
|
||||
first, last);
|
||||
}
|
||||
|
||||
template<class Pred>
|
||||
char const*
|
||||
find_if_not(
|
||||
char const* first,
|
||||
char const* const last,
|
||||
Pred const& pred,
|
||||
std::false_type) noexcept
|
||||
{
|
||||
while(first != last)
|
||||
{
|
||||
if(! pred(*first))
|
||||
break;
|
||||
++first;
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
template<class Pred>
|
||||
char const*
|
||||
find_if_not(
|
||||
char const* first,
|
||||
char const* const last,
|
||||
Pred const& pred,
|
||||
std::true_type) noexcept
|
||||
{
|
||||
return pred.find_if_not(
|
||||
first, last);
|
||||
}
|
||||
|
||||
#ifdef BOOST_URL_USE_SSE2
|
||||
|
||||
// by Peter Dimov
|
||||
template<class Pred>
|
||||
char const*
|
||||
find_if_pred(
|
||||
Pred const& pred,
|
||||
char const* first,
|
||||
char const* last ) noexcept
|
||||
{
|
||||
while( last - first >= 16 )
|
||||
{
|
||||
unsigned char r[ 16 ] = {};
|
||||
for( int i = 0; i < 16; ++i )
|
||||
r[ i ] = pred( first[ i ] )? 0xFF: 0x00;
|
||||
__m128i r2 = _mm_loadu_si128( (__m128i const*)r );
|
||||
unsigned r3 = _mm_movemask_epi8( r2 );
|
||||
if( r3 )
|
||||
return first + boost::core::countr_zero( r3 );
|
||||
first += 16;
|
||||
}
|
||||
while(
|
||||
first != last &&
|
||||
! pred(*first))
|
||||
{
|
||||
++first;
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
// by Peter Dimov
|
||||
template<class Pred>
|
||||
char const*
|
||||
find_if_not_pred(
|
||||
Pred const& pred,
|
||||
char const* first,
|
||||
char const* last ) noexcept
|
||||
{
|
||||
while( last - first >= 16 )
|
||||
{
|
||||
unsigned char r[ 16 ] = {};
|
||||
for( int i = 0; i < 16; ++i )
|
||||
r[ i ] = pred( first[ i ] )? 0x00: 0xFF;
|
||||
__m128i r2 = _mm_loadu_si128( (__m128i const*)r );
|
||||
unsigned r3 = _mm_movemask_epi8( r2 );
|
||||
if( r3 )
|
||||
return first + boost::core::countr_zero( r3 );
|
||||
first += 16;
|
||||
}
|
||||
while(
|
||||
first != last &&
|
||||
pred(*first))
|
||||
{
|
||||
++first;
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // detail
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_DETAIL_CI_STRING_HPP
|
||||
#define BOOST_URL_GRAMMAR_DETAIL_CI_STRING_HPP
|
||||
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
namespace detail {
|
||||
|
||||
template<class T, class = void>
|
||||
struct is_char_iter : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_char_iter<T, void_t<
|
||||
decltype(std::declval<char&>() =
|
||||
*std::declval<T const&>()),
|
||||
decltype(std::declval<T&>() =
|
||||
++std::declval<T&>()),
|
||||
decltype(std::declval<bool&>() =
|
||||
std::declval<T const&>() ==
|
||||
std::declval<T const&>())
|
||||
> > : std::integral_constant<bool,
|
||||
std::is_copy_constructible<T>::value>
|
||||
{
|
||||
};
|
||||
|
||||
template<class T, class = void>
|
||||
struct is_char_range : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_char_range<T, void_t<
|
||||
decltype(std::declval<T const&>().begin()),
|
||||
decltype(std::declval<T const&>().end())
|
||||
> > : std::integral_constant<bool,
|
||||
is_char_iter<decltype(
|
||||
std::declval<T const&>(
|
||||
).begin())>::value &&
|
||||
is_char_iter<decltype(
|
||||
std::declval<T const&>(
|
||||
).end())>::value>
|
||||
{
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct type_id_impl
|
||||
{
|
||||
static
|
||||
constexpr
|
||||
char cid = 0;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
constexpr
|
||||
char
|
||||
type_id_impl<T>::cid;
|
||||
|
||||
template<class T>
|
||||
constexpr
|
||||
std::uintptr_t
|
||||
type_id() noexcept
|
||||
{
|
||||
return std::uintptr_t(
|
||||
&type_id_impl<T>::cid);
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
constexpr
|
||||
char
|
||||
to_lower(char c) noexcept
|
||||
{
|
||||
return
|
||||
(c >= 'A' &&
|
||||
c <= 'Z')
|
||||
? c + 'a' - 'A'
|
||||
: c;
|
||||
}
|
||||
|
||||
constexpr
|
||||
char
|
||||
to_upper(char c) noexcept
|
||||
{
|
||||
return
|
||||
(c >= 'a' &&
|
||||
c <= 'z')
|
||||
? c - ('a' - 'A')
|
||||
: c;
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<class S0, class S1>
|
||||
auto
|
||||
ci_is_equal(
|
||||
S0 const& s0,
|
||||
S1 const& s1) ->
|
||||
typename std::enable_if<
|
||||
! std::is_convertible<
|
||||
S0, core::string_view>::value ||
|
||||
! std::is_convertible<
|
||||
S1, core::string_view>::value,
|
||||
bool>::type
|
||||
{
|
||||
/* If you get a compile error here, it
|
||||
means that a range you passed does
|
||||
not meet the requirements stated
|
||||
in the documentation.
|
||||
*/
|
||||
static_assert(
|
||||
is_char_range<S0>::value,
|
||||
"Type requirements not met");
|
||||
static_assert(
|
||||
is_char_range<S1>::value,
|
||||
"Type requirements not met");
|
||||
|
||||
// Arguments are sorted by type to
|
||||
// reduce the number of function
|
||||
// template instantiations. This
|
||||
// works because:
|
||||
//
|
||||
// ci_is_equal(s0,s1) == ci_is_equal(s1,s0)
|
||||
//
|
||||
BOOST_ASSERT(
|
||||
detail::type_id<S0>() <=
|
||||
detail::type_id<S1>());
|
||||
|
||||
auto it0 = s0.begin();
|
||||
auto it1 = s1.begin();
|
||||
auto const end0 = s0.end();
|
||||
auto const end1 = s1.end();
|
||||
for(;;)
|
||||
{
|
||||
if(it0 == end0)
|
||||
return it1 == end1;
|
||||
if(it1 == end1)
|
||||
return false;
|
||||
if( to_lower(*it0) !=
|
||||
to_lower(*it1))
|
||||
return false;
|
||||
++it0;
|
||||
++it1;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
BOOST_URL_DECL
|
||||
bool
|
||||
ci_is_equal(
|
||||
core::string_view s0,
|
||||
core::string_view s1) noexcept;
|
||||
|
||||
BOOST_URL_DECL
|
||||
bool
|
||||
ci_is_less(
|
||||
core::string_view s0,
|
||||
core::string_view s1) noexcept;
|
||||
|
||||
} // detail
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
//
|
||||
// Copyright (c) 2022 Vinnie Falco (vinnie.falco@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_GRAMMAR_DETAIL_RECYCLED_HPP
|
||||
#define BOOST_URL_GRAMMAR_DETAIL_RECYCLED_HPP
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
namespace detail {
|
||||
|
||||
template<
|
||||
std::size_t Size,
|
||||
std::size_t Align>
|
||||
struct aligned_storage_impl
|
||||
{
|
||||
void* addr() noexcept
|
||||
{
|
||||
return buf_;
|
||||
}
|
||||
|
||||
void const* addr() const noexcept
|
||||
{
|
||||
return buf_;
|
||||
}
|
||||
|
||||
private:
|
||||
alignas(Align)
|
||||
unsigned char buf_[Size];
|
||||
};
|
||||
|
||||
constexpr
|
||||
std::size_t
|
||||
nearest_pow2(
|
||||
std::size_t x,
|
||||
std::size_t f = 0) noexcept
|
||||
{
|
||||
return
|
||||
(f <= (std::size_t(-1)/2))
|
||||
? ( x <= f
|
||||
? f
|
||||
: nearest_pow2(x, 2 * f))
|
||||
: x;
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
BOOST_URL_DECL
|
||||
void
|
||||
recycled_add_impl(
|
||||
std::size_t) noexcept;
|
||||
|
||||
BOOST_URL_DECL
|
||||
void
|
||||
recycled_remove_impl(
|
||||
std::size_t) noexcept;
|
||||
|
||||
#ifdef BOOST_URL_REPORT
|
||||
|
||||
inline
|
||||
void
|
||||
recycled_add(
|
||||
std::size_t n) noexcept
|
||||
{
|
||||
recycled_add_impl(n);
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
recycled_remove(
|
||||
std::size_t n) noexcept
|
||||
{
|
||||
recycled_remove_impl(n);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline void recycled_add(
|
||||
std::size_t) noexcept
|
||||
{
|
||||
}
|
||||
inline void recycled_remove(
|
||||
std::size_t) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // detail
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Damian Jarek (damian dot jarek93 at gmail dot com)
|
||||
// Copyright (c) 2022 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
|
||||
//
|
||||
|
||||
#ifndef BOOST_URL_GRAMMAR_DETAIL_TUPLE_HPP
|
||||
#define BOOST_URL_GRAMMAR_DETAIL_TUPLE_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <boost/core/empty_value.hpp>
|
||||
#include <boost/mp11/algorithm.hpp>
|
||||
#include <boost/mp11/function.hpp>
|
||||
#include <boost/mp11/integer_sequence.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/copy_cv.hpp>
|
||||
#include <cstdlib>
|
||||
#include <utility>
|
||||
|
||||
#ifndef BOOST_URL_TUPLE_EBO
|
||||
// VFALCO No idea what causes it or how to fix it
|
||||
// https://devblogs.microsoft.com/cppblog/optimizing-the-layout-of-empty-base-classes-in-vs2015-update-2-3/
|
||||
#ifdef BOOST_MSVC
|
||||
#define BOOST_URL_TUPLE_EBO 0
|
||||
#else
|
||||
#define BOOST_URL_TUPLE_EBO 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
namespace detail {
|
||||
|
||||
#if BOOST_URL_TUPLE_EBO
|
||||
template<std::size_t I, class T>
|
||||
struct tuple_element_impl
|
||||
: empty_value<T>
|
||||
{
|
||||
constexpr
|
||||
tuple_element_impl(T const& t)
|
||||
: empty_value<T>(
|
||||
empty_init, t)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr
|
||||
tuple_element_impl(T&& t)
|
||||
: empty_value<T>(
|
||||
empty_init,
|
||||
std::move(t))
|
||||
{
|
||||
}
|
||||
};
|
||||
#else
|
||||
template<std::size_t I, class T>
|
||||
struct tuple_element_impl
|
||||
{
|
||||
T t_;
|
||||
|
||||
constexpr
|
||||
tuple_element_impl(T const& t)
|
||||
: t_(t)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr
|
||||
tuple_element_impl(T&& t)
|
||||
: t_(std::move(t))
|
||||
{
|
||||
}
|
||||
|
||||
constexpr
|
||||
T&
|
||||
get() noexcept
|
||||
{
|
||||
return t_;
|
||||
}
|
||||
|
||||
constexpr
|
||||
T const&
|
||||
get() const noexcept
|
||||
{
|
||||
return t_;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template<std::size_t I, class T>
|
||||
struct tuple_element_impl<I, T&>
|
||||
{
|
||||
T& t;
|
||||
|
||||
constexpr
|
||||
tuple_element_impl(T& t_)
|
||||
: t(t_)
|
||||
{
|
||||
}
|
||||
|
||||
T&
|
||||
get() const noexcept
|
||||
{
|
||||
return t;
|
||||
}
|
||||
};
|
||||
|
||||
template<class... Ts>
|
||||
struct tuple_impl;
|
||||
|
||||
template<class... Ts, std::size_t... Is>
|
||||
struct tuple_impl<
|
||||
mp11::index_sequence<Is...>, Ts...>
|
||||
: tuple_element_impl<Is, Ts>...
|
||||
{
|
||||
template<class... Us>
|
||||
constexpr
|
||||
explicit
|
||||
tuple_impl(Us&&... us)
|
||||
: tuple_element_impl<Is, Ts>(
|
||||
std::forward<Us>(us))...
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class... Ts>
|
||||
struct tuple
|
||||
: tuple_impl<
|
||||
mp11::index_sequence_for<Ts...>, Ts...>
|
||||
{
|
||||
template<class... Us,
|
||||
typename std::enable_if<
|
||||
mp11::mp_bool<
|
||||
mp11::mp_all<std::is_constructible<
|
||||
Ts, Us>...>::value &&
|
||||
! mp11::mp_all<std::is_convertible<
|
||||
Us, Ts>...>::value>::value,
|
||||
int>::type = 0
|
||||
>
|
||||
constexpr
|
||||
explicit
|
||||
tuple(Us&&... us) noexcept
|
||||
: tuple_impl<mp11::index_sequence_for<
|
||||
Ts...>, Ts...>{std::forward<Us>(us)...}
|
||||
{
|
||||
}
|
||||
|
||||
template<class... Us,
|
||||
typename std::enable_if<
|
||||
mp11::mp_all<std::is_convertible<
|
||||
Us, Ts>...>::value,
|
||||
int>::type = 0
|
||||
>
|
||||
constexpr
|
||||
tuple(Us&&... us) noexcept
|
||||
: tuple_impl<mp11::index_sequence_for<
|
||||
Ts...>, Ts...>{std::forward<Us>(us)...}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<std::size_t I, class T>
|
||||
constexpr
|
||||
T&
|
||||
get(tuple_element_impl<I, T>& te)
|
||||
{
|
||||
return te.get();
|
||||
}
|
||||
|
||||
template<std::size_t I, class T>
|
||||
constexpr
|
||||
T const&
|
||||
get(tuple_element_impl<I, T> const& te)
|
||||
{
|
||||
return te.get();
|
||||
}
|
||||
|
||||
template<std::size_t I, class T>
|
||||
constexpr
|
||||
T&&
|
||||
get(tuple_element_impl<I, T>&& te)
|
||||
{
|
||||
return std::move(te.get());
|
||||
}
|
||||
|
||||
template<std::size_t I, class T>
|
||||
constexpr
|
||||
T&
|
||||
get(tuple_element_impl<I, T&>&& te)
|
||||
{
|
||||
return te.get();
|
||||
}
|
||||
|
||||
template<std::size_t I, class T>
|
||||
using tuple_element =
|
||||
typename boost::copy_cv<
|
||||
mp11::mp_at_c<typename
|
||||
remove_cv<T>::type,
|
||||
I>, T>::type;
|
||||
|
||||
} // detail
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
//
|
||||
// Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_DIGIT_CHARS_HPP
|
||||
#define BOOST_URL_GRAMMAR_DIGIT_CHARS_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/grammar/detail/charset.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** The set of decimal digits
|
||||
|
||||
@par Example
|
||||
Character sets are used with rules and the
|
||||
functions @ref find_if and @ref find_if_not.
|
||||
@code
|
||||
system::result< core::string_view > rv = parse( "2022", token_rule( digit_chars ) );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
DIGIT = %x30-39
|
||||
; 0-9
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc5234#appendix-B.1"
|
||||
>B.1. Core Rules (rfc5234)</a>
|
||||
|
||||
@see
|
||||
@ref find_if,
|
||||
@ref find_if_not,
|
||||
@ref parse,
|
||||
@ref token_rule.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
constexpr __implementation_defined__ digit_chars;
|
||||
#else
|
||||
struct digit_chars_t
|
||||
{
|
||||
constexpr
|
||||
bool
|
||||
operator()(char c) const noexcept
|
||||
{
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
#ifdef BOOST_URL_USE_SSE2
|
||||
char const*
|
||||
find_if(
|
||||
char const* first,
|
||||
char const* last) const noexcept
|
||||
{
|
||||
return detail::find_if_pred(
|
||||
*this, first, last);
|
||||
}
|
||||
|
||||
char const*
|
||||
find_if_not(
|
||||
char const* first,
|
||||
char const* last) const noexcept
|
||||
{
|
||||
return detail::find_if_not_pred(
|
||||
*this, first, last);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
constexpr digit_chars_t digit_chars{};
|
||||
#endif
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_GRAMMAR_ERROR_HPP
|
||||
#define BOOST_URL_GRAMMAR_ERROR_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** Error codes returned when using rules
|
||||
|
||||
@see
|
||||
@ref condition,
|
||||
@ref parse.
|
||||
*/
|
||||
enum class error
|
||||
{
|
||||
// VFALCO 3 space indent or
|
||||
// else Doxygen malfunctions
|
||||
|
||||
//
|
||||
// (informational)
|
||||
//
|
||||
|
||||
/**
|
||||
* More input is needed to match the rule
|
||||
*
|
||||
* A rule reached the end of the input,
|
||||
* resulting in a partial match. The error
|
||||
* is recoverable; the caller may obtain
|
||||
* more input if possible and attempt to
|
||||
* parse the character buffer again.
|
||||
* Custom rules should only return this
|
||||
* error if it is completely unambiguous
|
||||
* that the rule cannot be matched without
|
||||
* more input.
|
||||
*/
|
||||
need_more = 1,
|
||||
|
||||
/**
|
||||
* The rule did not match the input.
|
||||
*
|
||||
* This error is returned when a rule fails
|
||||
* to match the input. The error is recoverable;
|
||||
* the caller may rewind the input pointer and
|
||||
* attempt to parse again using a different rule.
|
||||
*/
|
||||
mismatch,
|
||||
|
||||
/**
|
||||
* A rule reached the end of a range
|
||||
*
|
||||
* This indicates that the input was consumed
|
||||
* when parsing a @ref range. The @ref range_rule
|
||||
* avoids rewinding the input buffer when
|
||||
* this error is returned. Thus the consumed
|
||||
* characters are be considered part of the
|
||||
* range without contributing additional
|
||||
* elements.
|
||||
*/
|
||||
end_of_range,
|
||||
|
||||
/**
|
||||
* Leftover input remaining after match.
|
||||
*/
|
||||
leftover,
|
||||
|
||||
//--------------------------------------------
|
||||
//
|
||||
// condition::fatal
|
||||
//
|
||||
//--------------------------------------------
|
||||
|
||||
/**
|
||||
* A rule encountered unrecoverable invalid input.
|
||||
*
|
||||
* This error is returned when input is matching
|
||||
* but one of the requirements is violated. For
|
||||
* example if a percent escape is found, but
|
||||
* one or both characters that follow are not
|
||||
* valid hexadecimal digits. This is usually an
|
||||
* unrecoverable error.
|
||||
*/
|
||||
invalid,
|
||||
|
||||
/** An integer overflowed during parsing.
|
||||
*/
|
||||
out_of_range,
|
||||
|
||||
/**
|
||||
* An unspecified syntax error was found.
|
||||
*/
|
||||
syntax
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Error conditions for errors received from rules
|
||||
|
||||
@see
|
||||
@ref error,
|
||||
@ref parse.
|
||||
*/
|
||||
enum class condition
|
||||
{
|
||||
/**
|
||||
* A fatal error in syntax was encountered.
|
||||
|
||||
This indicates that parsing cannot continue.
|
||||
*/
|
||||
fatal = 1
|
||||
};
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#include <boost/url/grammar/impl/error.hpp>
|
||||
|
||||
#endif
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
//
|
||||
// Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_HEXDIG_CHARS_HPP
|
||||
#define BOOST_URL_GRAMMAR_HEXDIG_CHARS_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/grammar/detail/charset.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** The set of hexadecimal digits
|
||||
|
||||
@par Example
|
||||
Character sets are used with rules and the
|
||||
functions @ref find_if and @ref find_if_not.
|
||||
@code
|
||||
system::result< core::string_view > rv = parse( "8086FC19", token_rule( hexdig_chars ) );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
HEXDIG = DIGIT
|
||||
/ "A" / "B" / "C" / "D" / "E" / "F"
|
||||
/ "a" / "b" / "c" / "d" / "e" / "f"
|
||||
@endcode
|
||||
|
||||
@note The RFCs are inconsistent on the case
|
||||
sensitivity of hexadecimal digits. Existing
|
||||
uses suggest case-insensitivity is a de-facto
|
||||
standard.
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc5234#appendix-B.1"
|
||||
>B.1. Core Rules (rfc5234)</a>
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc7230#section-1.2"
|
||||
>1.2. Syntax Notation (rfc7230)</a>
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc5952#section-2.3"
|
||||
>2.3. Uppercase or Lowercase (rfc5952)</a>
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc5952#section-4.3"
|
||||
>4.3. Lowercase (rfc5952)</a>
|
||||
|
||||
@see
|
||||
@ref find_if,
|
||||
@ref find_if_not,
|
||||
@ref hexdig_value,
|
||||
@ref parse,
|
||||
@ref token_rule.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
constexpr __implementation_defined__ hexdig_chars;
|
||||
#else
|
||||
struct hexdig_chars_t
|
||||
{
|
||||
/** Return true if c is in the character set.
|
||||
*/
|
||||
constexpr
|
||||
bool
|
||||
operator()(char c) const noexcept
|
||||
{
|
||||
return
|
||||
(c >= '0' && c <= '9') ||
|
||||
(c >= 'A' && c <= 'F') ||
|
||||
(c >= 'a' && c <= 'f');
|
||||
}
|
||||
|
||||
#ifdef BOOST_URL_USE_SSE2
|
||||
char const*
|
||||
find_if(
|
||||
char const* first,
|
||||
char const* last) const noexcept
|
||||
{
|
||||
return detail::find_if_pred(
|
||||
*this, first, last);
|
||||
}
|
||||
|
||||
char const*
|
||||
find_if_not(
|
||||
char const* first,
|
||||
char const* last) const noexcept
|
||||
{
|
||||
return detail::find_if_not_pred(
|
||||
*this, first, last);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
constexpr hexdig_chars_t hexdig_chars{};
|
||||
#endif
|
||||
|
||||
// VFALCO We can declare
|
||||
// these later if needed
|
||||
//
|
||||
//struct hexdig_upper_chars;
|
||||
//struct hexdig_lower_chars;
|
||||
|
||||
/** Return the decimal value of a hex character
|
||||
|
||||
This function returns the decimal
|
||||
value of a hexadecimal character,
|
||||
or -1 if the argument is not a
|
||||
valid hexadecimal digit.
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
HEXDIG = DIGIT
|
||||
/ "A" / "B" / "C" / "D" / "E" / "F"
|
||||
/ "a" / "b" / "c" / "d" / "e" / "f"
|
||||
@endcode
|
||||
|
||||
@param ch The character to check
|
||||
|
||||
@return The decimal value or -1
|
||||
*/
|
||||
inline
|
||||
signed char
|
||||
hexdig_value(char ch) noexcept
|
||||
{
|
||||
// Idea for switch statement to
|
||||
// minimize emitted assembly from
|
||||
// Glen Fernandes
|
||||
signed char res;
|
||||
switch(ch)
|
||||
{
|
||||
default: res = -1; break;
|
||||
case '0': res = 0; break;
|
||||
case '1': res = 1; break;
|
||||
case '2': res = 2; break;
|
||||
case '3': res = 3; break;
|
||||
case '4': res = 4; break;
|
||||
case '5': res = 5; break;
|
||||
case '6': res = 6; break;
|
||||
case '7': res = 7; break;
|
||||
case '8': res = 8; break;
|
||||
case '9': res = 9; break;
|
||||
case 'a': case 'A': res = 10; break;
|
||||
case 'b': case 'B': res = 11; break;
|
||||
case 'c': case 'C': res = 12; break;
|
||||
case 'd': case 'D': res = 13; break;
|
||||
case 'e': case 'E': res = 14; break;
|
||||
case 'f': case 'F': res = 15; break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_GRAMMAR_IMPL_ERROR_HPP
|
||||
#define BOOST_URL_GRAMMAR_IMPL_ERROR_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace system {
|
||||
template<>
|
||||
struct is_error_code_enum<
|
||||
::boost::urls::grammar::error>
|
||||
{
|
||||
static bool const value = true;
|
||||
};
|
||||
template<>
|
||||
struct is_error_condition_enum<
|
||||
::boost::urls::grammar::condition>
|
||||
{
|
||||
static bool const value = true;
|
||||
};
|
||||
} // system
|
||||
} // boost
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct BOOST_SYMBOL_VISIBLE
|
||||
error_cat_type
|
||||
: system::error_category
|
||||
{
|
||||
BOOST_URL_DECL
|
||||
const char* name(
|
||||
) const noexcept override;
|
||||
|
||||
BOOST_URL_DECL
|
||||
std::string message(
|
||||
int) const override;
|
||||
|
||||
BOOST_URL_DECL
|
||||
char const* message(
|
||||
int, char*, std::size_t
|
||||
) const noexcept override;
|
||||
|
||||
BOOST_URL_DECL
|
||||
system::error_condition
|
||||
default_error_condition(
|
||||
int code) const noexcept override;
|
||||
|
||||
BOOST_SYSTEM_CONSTEXPR error_cat_type() noexcept
|
||||
: error_category(0x0536e50a30f9e9f2)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct BOOST_SYMBOL_VISIBLE
|
||||
condition_cat_type
|
||||
: system::error_category
|
||||
{
|
||||
BOOST_URL_DECL
|
||||
const char* name(
|
||||
) const noexcept override;
|
||||
|
||||
BOOST_URL_DECL
|
||||
std::string message(
|
||||
int) const override;
|
||||
|
||||
BOOST_URL_DECL
|
||||
char const* message(
|
||||
int, char*, std::size_t
|
||||
) const noexcept override;
|
||||
|
||||
BOOST_SYSTEM_CONSTEXPR condition_cat_type()
|
||||
: error_category(0x0536e50a30f9e9f2)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_URL_DECL extern
|
||||
error_cat_type error_cat;
|
||||
|
||||
BOOST_URL_DECL extern
|
||||
condition_cat_type condition_cat;
|
||||
|
||||
} // detail
|
||||
|
||||
inline
|
||||
system::error_code
|
||||
make_error_code(
|
||||
error ev) noexcept
|
||||
{
|
||||
return system::error_code{
|
||||
static_cast<std::underlying_type<
|
||||
error>::type>(ev),
|
||||
detail::error_cat};
|
||||
}
|
||||
|
||||
inline
|
||||
system::error_condition
|
||||
make_error_condition(
|
||||
condition c) noexcept
|
||||
{
|
||||
return system::error_condition{
|
||||
static_cast<std::underlying_type<
|
||||
condition>::type>(c),
|
||||
detail::condition_cat};
|
||||
}
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_IMPL_NOT_EMPTY_RULE_HPP
|
||||
#define BOOST_URL_GRAMMAR_IMPL_NOT_EMPTY_RULE_HPP
|
||||
|
||||
#include <boost/url/grammar/error.hpp>
|
||||
#include <boost/url/grammar/parse.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
template<class R>
|
||||
auto
|
||||
not_empty_rule_t<R>::
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const ->
|
||||
system::result<value_type>
|
||||
{
|
||||
if(it == end)
|
||||
{
|
||||
// empty
|
||||
BOOST_URL_RETURN_EC(
|
||||
error::mismatch);
|
||||
}
|
||||
auto const it0 = it;
|
||||
auto rv = r_.parse(it, end);
|
||||
if( !rv )
|
||||
{
|
||||
// error
|
||||
return rv;
|
||||
}
|
||||
if(it == it0)
|
||||
{
|
||||
// empty
|
||||
BOOST_URL_RETURN_EC(
|
||||
error::mismatch);
|
||||
}
|
||||
// value
|
||||
return rv;
|
||||
}
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_IMPL_OPTIONAL_RULE_HPP
|
||||
#define BOOST_URL_GRAMMAR_IMPL_OPTIONAL_RULE_HPP
|
||||
|
||||
#include <boost/url/grammar/error.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
template<class R>
|
||||
auto
|
||||
optional_rule_t<R>::
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const ->
|
||||
system::result<value_type>
|
||||
{
|
||||
if(it == end)
|
||||
return boost::none;
|
||||
auto const it0 = it;
|
||||
auto rv =
|
||||
this->get().parse(it, end);
|
||||
if(rv)
|
||||
return value_type(*rv);
|
||||
it = it0;
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_IMPL_PARSE_HPP
|
||||
#define BOOST_URL_GRAMMAR_IMPL_PARSE_HPP
|
||||
|
||||
#include <boost/url/grammar/error.hpp>
|
||||
#include <boost/url/grammar/type_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
template<class R>
|
||||
BOOST_URL_NO_INLINE
|
||||
auto
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end,
|
||||
R const& r) ->
|
||||
system::result<typename R::value_type>
|
||||
{
|
||||
// If this goes off, it means the rule
|
||||
// passed in did not meet the requirements.
|
||||
// Please check the documentation.
|
||||
static_assert(
|
||||
is_rule<R>::value,
|
||||
"Rule requirements not met");
|
||||
|
||||
return r.parse(it, end);
|
||||
}
|
||||
|
||||
template<class R>
|
||||
BOOST_URL_NO_INLINE
|
||||
auto
|
||||
parse(
|
||||
core::string_view s,
|
||||
R const& r) ->
|
||||
system::result<typename R::value_type>
|
||||
{
|
||||
// If this goes off, it means the rule
|
||||
// passed in did not meet the requirements.
|
||||
// Please check the documentation.
|
||||
static_assert(
|
||||
is_rule<R>::value,
|
||||
"Rule requirements not met");
|
||||
|
||||
auto it = s.data();
|
||||
auto const end = it + s.size();
|
||||
auto rv = r.parse(it, end);
|
||||
if( rv &&
|
||||
it != end)
|
||||
return error::leftover;
|
||||
return rv;
|
||||
}
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+742
@@ -0,0 +1,742 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_IMPL_RANGE_HPP
|
||||
#define BOOST_URL_GRAMMAR_IMPL_RANGE_HPP
|
||||
|
||||
#include <boost/url/detail/except.hpp>
|
||||
#include <boost/url/grammar/error.hpp>
|
||||
#include <boost/url/grammar/recycled.hpp>
|
||||
#include <boost/core/empty_value.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <exception>
|
||||
#include <iterator>
|
||||
#include <new>
|
||||
|
||||
#include <stddef.h> // ::max_align_t
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
// VFALCO This could be reused for
|
||||
// other things that need to type-erase
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// any_rule
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
// base class for the type-erased rule pair
|
||||
template<class T>
|
||||
struct range<T>::
|
||||
any_rule
|
||||
{
|
||||
virtual
|
||||
~any_rule() = default;
|
||||
|
||||
virtual
|
||||
void
|
||||
move(void* dest) noexcept
|
||||
{
|
||||
::new(dest) any_rule(
|
||||
std::move(*this));
|
||||
}
|
||||
|
||||
virtual
|
||||
void
|
||||
copy(void* dest) const noexcept
|
||||
{
|
||||
::new(dest) any_rule(*this);
|
||||
}
|
||||
|
||||
virtual
|
||||
system::result<T>
|
||||
first(
|
||||
char const*&,
|
||||
char const*) const noexcept
|
||||
{
|
||||
return system::error_code{};
|
||||
}
|
||||
|
||||
virtual
|
||||
system::result<T>
|
||||
next(
|
||||
char const*&,
|
||||
char const*) const noexcept
|
||||
{
|
||||
return system::error_code{};
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
// small
|
||||
template<class T>
|
||||
template<class R, bool Small>
|
||||
struct range<T>::impl1
|
||||
: any_rule
|
||||
, private empty_value<R>
|
||||
{
|
||||
explicit
|
||||
impl1(R const& next) noexcept
|
||||
: empty_value<R>(
|
||||
empty_init,
|
||||
next)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
impl1(impl1&&) noexcept = default;
|
||||
impl1(impl1 const&) noexcept = default;
|
||||
|
||||
void
|
||||
move(void* dest
|
||||
) noexcept override
|
||||
{
|
||||
::new(dest) impl1(
|
||||
std::move(*this));
|
||||
}
|
||||
|
||||
void
|
||||
copy(void* dest
|
||||
) const noexcept override
|
||||
{
|
||||
::new(dest) impl1(*this);
|
||||
}
|
||||
|
||||
system::result<T>
|
||||
first(
|
||||
char const*& it,
|
||||
char const* end)
|
||||
const noexcept override
|
||||
{
|
||||
return grammar::parse(
|
||||
it, end, this->get());
|
||||
}
|
||||
|
||||
system::result<T>
|
||||
next(
|
||||
char const*& it,
|
||||
char const* end)
|
||||
const noexcept override
|
||||
{
|
||||
return grammar::parse(
|
||||
it, end, this->get());
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
// big
|
||||
template<class T>
|
||||
template<class R>
|
||||
struct range<T>::impl1<R, false>
|
||||
: any_rule
|
||||
{
|
||||
explicit
|
||||
impl1(R const& next) noexcept
|
||||
{
|
||||
::new(p_->addr()) impl{next};
|
||||
}
|
||||
|
||||
private:
|
||||
struct impl
|
||||
{
|
||||
R r;
|
||||
};
|
||||
|
||||
recycled_ptr<
|
||||
aligned_storage<impl>> p_;
|
||||
|
||||
impl1(impl1&&) noexcept = default;
|
||||
impl1(impl1 const&) noexcept = default;
|
||||
|
||||
impl const&
|
||||
get() const noexcept
|
||||
{
|
||||
return *reinterpret_cast<
|
||||
impl const*>(p_->addr());
|
||||
}
|
||||
|
||||
~impl1()
|
||||
{
|
||||
if(p_)
|
||||
get().~impl();
|
||||
}
|
||||
|
||||
void
|
||||
move(void* dest
|
||||
) noexcept override
|
||||
{
|
||||
::new(dest) impl1(
|
||||
std::move(*this));
|
||||
}
|
||||
|
||||
void
|
||||
copy(void* dest
|
||||
) const noexcept override
|
||||
{
|
||||
::new(dest) impl1(*this);
|
||||
}
|
||||
|
||||
system::result<T>
|
||||
first(
|
||||
char const*& it,
|
||||
char const* end)
|
||||
const noexcept override
|
||||
{
|
||||
return grammar::parse(
|
||||
it, end, this->get().r);
|
||||
}
|
||||
|
||||
system::result<T>
|
||||
next(
|
||||
char const*& it,
|
||||
char const* end)
|
||||
const noexcept override
|
||||
{
|
||||
return grammar::parse(
|
||||
it, end, this->get().r);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
// small
|
||||
template<class T>
|
||||
template<
|
||||
class R0, class R1, bool Small>
|
||||
struct range<T>::impl2
|
||||
: any_rule
|
||||
, private empty_value<R0, 0>
|
||||
, private empty_value<R1, 1>
|
||||
{
|
||||
impl2(
|
||||
R0 const& first,
|
||||
R1 const& next) noexcept
|
||||
: empty_value<R0,0>(
|
||||
empty_init, first)
|
||||
, empty_value<R1,1>(
|
||||
empty_init, next)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
impl2(impl2&&) noexcept = default;
|
||||
impl2(impl2 const&) noexcept = default;
|
||||
|
||||
void
|
||||
move(void* dest
|
||||
) noexcept override
|
||||
{
|
||||
::new(dest) impl2(
|
||||
std::move(*this));
|
||||
}
|
||||
|
||||
void
|
||||
copy(void* dest
|
||||
) const noexcept override
|
||||
{
|
||||
::new(dest) impl2(*this);
|
||||
}
|
||||
|
||||
system::result<T>
|
||||
first(
|
||||
char const*& it,
|
||||
char const* end)
|
||||
const noexcept override
|
||||
{
|
||||
return grammar::parse(it, end,
|
||||
empty_value<
|
||||
R0,0>::get());
|
||||
}
|
||||
|
||||
system::result<T>
|
||||
next(
|
||||
char const*& it,
|
||||
char const* end)
|
||||
const noexcept override
|
||||
{
|
||||
return grammar::parse(it, end,
|
||||
empty_value<
|
||||
R1,1>::get());
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
// big
|
||||
template<class T>
|
||||
template<
|
||||
class R0, class R1>
|
||||
struct range<T>::impl2<R0, R1, false>
|
||||
: any_rule
|
||||
{
|
||||
impl2(
|
||||
R0 const& first,
|
||||
R1 const& next) noexcept
|
||||
{
|
||||
::new(p_->addr()) impl{
|
||||
first, next};
|
||||
}
|
||||
|
||||
private:
|
||||
struct impl
|
||||
{
|
||||
R0 first;
|
||||
R1 next;
|
||||
};
|
||||
|
||||
recycled_ptr<
|
||||
aligned_storage<impl>> p_;
|
||||
|
||||
impl2(impl2&&) noexcept = default;
|
||||
impl2(impl2 const&) noexcept = default;
|
||||
|
||||
impl const&
|
||||
get() const noexcept
|
||||
{
|
||||
return *reinterpret_cast<
|
||||
impl const*>(p_->addr());
|
||||
}
|
||||
|
||||
~impl2()
|
||||
{
|
||||
if(p_)
|
||||
get().~impl();
|
||||
}
|
||||
|
||||
void
|
||||
move(void* dest
|
||||
) noexcept override
|
||||
{
|
||||
::new(dest) impl2(
|
||||
std::move(*this));
|
||||
}
|
||||
|
||||
void
|
||||
copy(void* dest
|
||||
) const noexcept override
|
||||
{
|
||||
::new(dest) impl2(*this);
|
||||
}
|
||||
|
||||
system::result<T>
|
||||
first(
|
||||
char const*& it,
|
||||
char const* end)
|
||||
const noexcept override
|
||||
{
|
||||
return grammar::parse(
|
||||
it, end, get().first);
|
||||
}
|
||||
|
||||
system::result<T>
|
||||
next(
|
||||
char const*& it,
|
||||
char const* end)
|
||||
const noexcept override
|
||||
{
|
||||
return grammar::parse(
|
||||
it, end, get().next);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// iterator
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
template<class T>
|
||||
class range<T>::
|
||||
iterator
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
using reference = T const&;
|
||||
using pointer = void const*;
|
||||
using difference_type =
|
||||
std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::forward_iterator_tag;
|
||||
|
||||
iterator() = default;
|
||||
iterator(
|
||||
iterator const&) = default;
|
||||
iterator& operator=(
|
||||
iterator const&) = default;
|
||||
|
||||
reference
|
||||
operator*() const noexcept
|
||||
{
|
||||
return *rv_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
// can't compare iterators
|
||||
// from different containers!
|
||||
BOOST_ASSERT(r_ == other.r_);
|
||||
|
||||
return p_ == other.p_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
iterator&
|
||||
operator++() noexcept
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
p_ != nullptr);
|
||||
auto const end =
|
||||
r_->s_.data() +
|
||||
r_->s_.size();
|
||||
rv_ = r_->get().next(p_, end);
|
||||
if( !rv_ )
|
||||
p_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator
|
||||
operator++(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class range<T>;
|
||||
|
||||
range<T> const* r_ = nullptr;
|
||||
char const* p_ = nullptr;
|
||||
system::result<T> rv_;
|
||||
|
||||
iterator(
|
||||
range<T> const& r) noexcept
|
||||
: r_(&r)
|
||||
, p_(r.s_.data())
|
||||
{
|
||||
auto const end =
|
||||
r_->s_.data() +
|
||||
r_->s_.size();
|
||||
rv_ = r_->get().first(p_, end);
|
||||
if( !rv_ )
|
||||
p_ = nullptr;
|
||||
}
|
||||
|
||||
constexpr
|
||||
iterator(
|
||||
range<T> const& r,
|
||||
int) noexcept
|
||||
: r_(&r)
|
||||
, p_(nullptr)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<class T>
|
||||
template<class R>
|
||||
range<T>::
|
||||
range(
|
||||
core::string_view s,
|
||||
std::size_t n,
|
||||
R const& next)
|
||||
: s_(s)
|
||||
, n_(n)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
sizeof(impl1<R, false>) <=
|
||||
BufferSize);
|
||||
|
||||
::new(&get()) impl1<R,
|
||||
sizeof(impl1<R, true>) <=
|
||||
BufferSize>(next);
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<class T>
|
||||
template<
|
||||
class R0, class R1>
|
||||
range<T>::
|
||||
range(
|
||||
core::string_view s,
|
||||
std::size_t n,
|
||||
R0 const& first,
|
||||
R1 const& next)
|
||||
: s_(s)
|
||||
, n_(n)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
sizeof(impl2<R0, R1, false>) <=
|
||||
BufferSize);
|
||||
|
||||
::new(&get()) impl2<R0, R1,
|
||||
sizeof(impl2<R0, R1, true>
|
||||
) <= BufferSize>(
|
||||
first, next);
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<class T>
|
||||
range<T>::
|
||||
~range()
|
||||
{
|
||||
get().~any_rule();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
range<T>::
|
||||
range() noexcept
|
||||
{
|
||||
::new(&get()) any_rule{};
|
||||
char const* it = nullptr;
|
||||
get().first(it, nullptr);
|
||||
get().next(it, nullptr);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
range<T>::
|
||||
range(
|
||||
range&& other) noexcept
|
||||
: s_(other.s_)
|
||||
, n_(other.n_)
|
||||
{
|
||||
other.s_ = {};
|
||||
other.n_ = {};
|
||||
other.get().move(&get());
|
||||
other.get().~any_rule();
|
||||
::new(&other.get()) any_rule{};
|
||||
}
|
||||
|
||||
template<class T>
|
||||
range<T>::
|
||||
range(
|
||||
range const& other) noexcept
|
||||
: s_(other.s_)
|
||||
, n_(other.n_)
|
||||
{
|
||||
other.get().copy(&get());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
auto
|
||||
range<T>::
|
||||
operator=(
|
||||
range&& other) noexcept ->
|
||||
range&
|
||||
{
|
||||
s_ = other.s_;
|
||||
n_ = other.n_;
|
||||
other.s_ = {};
|
||||
other.n_ = 0;
|
||||
// VFALCO we rely on nothrow move
|
||||
// construction here, but if necessary we
|
||||
// could move to a local buffer first.
|
||||
get().~any_rule();
|
||||
other.get().move(&get());
|
||||
other.get().~any_rule();
|
||||
::new(&other.get()) any_rule{};
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
auto
|
||||
range<T>::
|
||||
operator=(
|
||||
range const& other) noexcept ->
|
||||
range&
|
||||
{
|
||||
s_ = other.s_;
|
||||
n_ = other.n_;
|
||||
// VFALCO we rely on nothrow copy
|
||||
// construction here, but if necessary we
|
||||
// could construct to a local buffer first.
|
||||
get().~any_rule();
|
||||
other.get().copy(&get());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
auto
|
||||
range<T>::
|
||||
begin() const noexcept ->
|
||||
iterator
|
||||
{
|
||||
return { *this };
|
||||
}
|
||||
|
||||
template<class T>
|
||||
auto
|
||||
range<T>::
|
||||
end() const noexcept ->
|
||||
iterator
|
||||
{
|
||||
return { *this, 0 };
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<class R>
|
||||
auto
|
||||
range_rule_t<R>::
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const ->
|
||||
system::result<value_type>
|
||||
{
|
||||
using T = typename R::value_type;
|
||||
|
||||
std::size_t n = 0;
|
||||
auto const it0 = it;
|
||||
auto it1 = it;
|
||||
auto rv = (grammar::parse)(
|
||||
it, end, next_);
|
||||
if( !rv )
|
||||
{
|
||||
if(rv.error() != error::end_of_range)
|
||||
{
|
||||
// rewind unless error::end_of_range
|
||||
it = it1;
|
||||
}
|
||||
if(n < N_)
|
||||
{
|
||||
// too few
|
||||
BOOST_URL_RETURN_EC(
|
||||
error::mismatch);
|
||||
}
|
||||
// good
|
||||
return range<T>(
|
||||
core::string_view(it0, it - it0),
|
||||
n, next_);
|
||||
}
|
||||
for(;;)
|
||||
{
|
||||
++n;
|
||||
it1 = it;
|
||||
rv = (grammar::parse)(
|
||||
it, end, next_);
|
||||
if( !rv )
|
||||
{
|
||||
if(rv.error() != error::end_of_range)
|
||||
{
|
||||
// rewind unless error::end_of_range
|
||||
it = it1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(n >= M_)
|
||||
{
|
||||
// too many
|
||||
BOOST_URL_RETURN_EC(
|
||||
error::mismatch);
|
||||
}
|
||||
}
|
||||
if(n < N_)
|
||||
{
|
||||
// too few
|
||||
BOOST_URL_RETURN_EC(
|
||||
error::mismatch);
|
||||
}
|
||||
// good
|
||||
return range<T>(
|
||||
core::string_view(it0, it - it0),
|
||||
n, next_);
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<class R0, class R1>
|
||||
auto
|
||||
range_rule_t<R0, R1>::
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const ->
|
||||
system::result<range<typename
|
||||
R0::value_type>>
|
||||
{
|
||||
using T = typename R0::value_type;
|
||||
|
||||
std::size_t n = 0;
|
||||
auto const it0 = it;
|
||||
auto it1 = it;
|
||||
auto rv = (grammar::parse)(
|
||||
it, end, first_);
|
||||
if( !rv )
|
||||
{
|
||||
if(rv.error() != error::end_of_range)
|
||||
{
|
||||
// rewind unless error::end_of_range
|
||||
it = it1;
|
||||
}
|
||||
if(n < N_)
|
||||
{
|
||||
// too few
|
||||
BOOST_URL_RETURN_EC(
|
||||
error::mismatch);
|
||||
}
|
||||
// good
|
||||
return range<T>(
|
||||
core::string_view(it0, it - it0),
|
||||
n, first_, next_);
|
||||
}
|
||||
for(;;)
|
||||
{
|
||||
++n;
|
||||
it1 = it;
|
||||
rv = (grammar::parse)(
|
||||
it, end, next_);
|
||||
if( !rv )
|
||||
{
|
||||
if(rv.error() != error::end_of_range)
|
||||
{
|
||||
// rewind unless error::end_of_range
|
||||
it = it1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(n >= M_)
|
||||
{
|
||||
// too many
|
||||
BOOST_URL_RETURN_EC(
|
||||
error::mismatch);
|
||||
}
|
||||
}
|
||||
if(n < N_)
|
||||
{
|
||||
// too few
|
||||
BOOST_URL_RETURN_EC(
|
||||
error::mismatch);
|
||||
}
|
||||
// good
|
||||
return range<T>(
|
||||
core::string_view(it0, it - it0),
|
||||
n, first_, next_);
|
||||
}
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
//
|
||||
// Copyright (c) 2022 Vinnie Falco (vinnie.falco@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_GRAMMAR_IMPL_RECYCLED_PTR_HPP
|
||||
#define BOOST_URL_GRAMMAR_IMPL_RECYCLED_PTR_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<class T>
|
||||
recycled<T>::
|
||||
~recycled()
|
||||
{
|
||||
std::size_t n = 0;
|
||||
// VFALCO we should probably deallocate
|
||||
// in reverse order of allocation but
|
||||
// that requires a doubly-linked list.
|
||||
auto it = head_;
|
||||
while(it)
|
||||
{
|
||||
++n;
|
||||
auto next = it->next;
|
||||
BOOST_ASSERT(
|
||||
it->refs == 0);
|
||||
delete it;
|
||||
it = next;
|
||||
}
|
||||
detail::recycled_remove(
|
||||
sizeof(U) * n);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
auto
|
||||
recycled<T>::
|
||||
acquire() ->
|
||||
U*
|
||||
{
|
||||
U* p;
|
||||
{
|
||||
#if !defined(BOOST_URL_DISABLE_THREADS)
|
||||
std::lock_guard<
|
||||
std::mutex> lock(m_);
|
||||
#endif
|
||||
p = head_;
|
||||
if(p)
|
||||
{
|
||||
// reuse
|
||||
head_ = head_->next;
|
||||
detail::recycled_remove(
|
||||
sizeof(U));
|
||||
++p->refs;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = new U;
|
||||
}
|
||||
}
|
||||
BOOST_ASSERT(p->refs == 1);
|
||||
return p;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
recycled<T>::
|
||||
release(U* u) noexcept
|
||||
{
|
||||
if(--u->refs != 0)
|
||||
return;
|
||||
{
|
||||
#if !defined(BOOST_URL_DISABLE_THREADS)
|
||||
std::lock_guard<
|
||||
std::mutex> lock(m_);
|
||||
#endif
|
||||
u->next = head_;
|
||||
head_ = u;
|
||||
}
|
||||
detail::recycled_add(
|
||||
sizeof(U));
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<class T>
|
||||
recycled_ptr<T>::
|
||||
~recycled_ptr()
|
||||
{
|
||||
if(p_)
|
||||
bin_->release(p_);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
recycled_ptr<T>::
|
||||
recycled_ptr(
|
||||
recycled<T>& bin)
|
||||
: bin_(&bin)
|
||||
, p_(bin.acquire())
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
recycled_ptr<T>::
|
||||
recycled_ptr(
|
||||
recycled<T>& bin,
|
||||
std::nullptr_t) noexcept
|
||||
: bin_(&bin)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
recycled_ptr<T>::
|
||||
recycled_ptr()
|
||||
: recycled_ptr(nullptr)
|
||||
{
|
||||
p_ = bin_->acquire();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
recycled_ptr<T>::
|
||||
recycled_ptr(
|
||||
std::nullptr_t) noexcept
|
||||
: recycled_ptr([]() -> B&
|
||||
{
|
||||
// VFALCO need guaranteed constexpr-init
|
||||
static B r;
|
||||
return r;
|
||||
}(), nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
recycled_ptr<T>::
|
||||
recycled_ptr(
|
||||
recycled_ptr const& other) noexcept
|
||||
: bin_(other.bin_)
|
||||
, p_(other.p_)
|
||||
{
|
||||
if(p_)
|
||||
++p_->refs;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
recycled_ptr<T>::
|
||||
recycled_ptr(
|
||||
recycled_ptr&& other) noexcept
|
||||
: bin_(other.bin_)
|
||||
, p_(other.p_)
|
||||
{
|
||||
other.p_ = nullptr;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
auto
|
||||
recycled_ptr<T>::
|
||||
operator=(
|
||||
recycled_ptr&& other) noexcept ->
|
||||
recycled_ptr&
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
bin_ == other.bin_);
|
||||
if(p_)
|
||||
bin_->release(p_);
|
||||
p_ = other.p_;
|
||||
other.p_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
auto
|
||||
recycled_ptr<T>::
|
||||
operator=(
|
||||
recycled_ptr const& other) noexcept ->
|
||||
recycled_ptr&
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
bin_ == other.bin_);
|
||||
if(p_)
|
||||
bin_->release(p_);
|
||||
p_ = other.p_;
|
||||
if(p_)
|
||||
++p_->refs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T&
|
||||
recycled_ptr<T>::
|
||||
acquire()
|
||||
{
|
||||
if(! p_)
|
||||
p_ = bin_->acquire();
|
||||
return p_->t;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
recycled_ptr<T>::
|
||||
release() noexcept
|
||||
{
|
||||
if(p_)
|
||||
{
|
||||
bin_->release(p_);
|
||||
p_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/http_proto
|
||||
//
|
||||
|
||||
#ifndef BOOST_URL_IMPL_GRAMMAR_TOKEN_RULE_HPP
|
||||
#define BOOST_URL_IMPL_GRAMMAR_TOKEN_RULE_HPP
|
||||
|
||||
#include <boost/url/grammar/error.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
template<class CharSet>
|
||||
auto
|
||||
token_rule_t<CharSet>::
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end
|
||||
) const noexcept ->
|
||||
system::result<value_type>
|
||||
{
|
||||
auto const it0 = it;
|
||||
if(it == end)
|
||||
{
|
||||
BOOST_URL_RETURN_EC(
|
||||
error::need_more);
|
||||
}
|
||||
it = (find_if_not)(it, end, cs_);
|
||||
if(it != it0)
|
||||
return core::string_view(it0, it - it0);
|
||||
BOOST_URL_RETURN_EC(
|
||||
error::mismatch);
|
||||
}
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+285
@@ -0,0 +1,285 @@
|
||||
//
|
||||
// Copyright (c) 2022 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_IMPL_TUPLE_RULE_HPP
|
||||
#define BOOST_URL_GRAMMAR_IMPL_TUPLE_RULE_HPP
|
||||
|
||||
#include <boost/url/grammar/parse.hpp>
|
||||
#include <boost/mp11/integral.hpp>
|
||||
#include <boost/mp11/list.hpp>
|
||||
#include <boost/mp11/tuple.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// returns a tuple
|
||||
template<
|
||||
bool IsList,
|
||||
class R0, class... Rn>
|
||||
struct parse_sequence
|
||||
{
|
||||
using R = detail::tuple<R0, Rn...>;
|
||||
|
||||
using L = mp11::mp_list<
|
||||
typename R0::value_type,
|
||||
typename Rn::value_type...>;
|
||||
|
||||
using V = mp11::mp_remove<
|
||||
std::tuple<
|
||||
system::result<typename R0::value_type>,
|
||||
system::result<typename Rn::value_type>...>,
|
||||
system::result<void>>;
|
||||
|
||||
template<std::size_t I>
|
||||
using is_void = std::is_same<
|
||||
mp11::mp_at_c<L, I>, void>;
|
||||
|
||||
system::error_code ec;
|
||||
R const& rn;
|
||||
V vn;
|
||||
|
||||
explicit
|
||||
parse_sequence(
|
||||
R const& rn_) noexcept
|
||||
: rn(rn_)
|
||||
, vn(mp11::mp_fill<
|
||||
V, system::error_code>{})
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
apply(
|
||||
char const*&,
|
||||
char const*,
|
||||
...) const noexcept
|
||||
{
|
||||
}
|
||||
|
||||
// for system::result<void>
|
||||
template<
|
||||
std::size_t Ir,
|
||||
std::size_t Iv>
|
||||
void
|
||||
apply(
|
||||
char const*& it,
|
||||
char const* end,
|
||||
mp11::mp_size_t<Ir> const&,
|
||||
mp11::mp_size_t<Iv> const&,
|
||||
mp11::mp_true const&)
|
||||
{
|
||||
system::result<void> rv =
|
||||
grammar::parse(
|
||||
it, end, get<Ir>(rn));
|
||||
if( !rv )
|
||||
{
|
||||
ec = rv.error();
|
||||
return;
|
||||
}
|
||||
apply(it, end,
|
||||
mp11::mp_size_t<Ir+1>{},
|
||||
mp11::mp_size_t<Iv>{});
|
||||
}
|
||||
|
||||
template<
|
||||
std::size_t Ir,
|
||||
std::size_t Iv>
|
||||
void
|
||||
apply(
|
||||
char const*& it,
|
||||
char const* end,
|
||||
mp11::mp_size_t<Ir> const&,
|
||||
mp11::mp_size_t<Iv> const&,
|
||||
mp11::mp_false const&)
|
||||
{
|
||||
auto& rv = get<Iv>(vn);
|
||||
rv = grammar::parse(
|
||||
it, end, get<Ir>(rn));
|
||||
if( !rv )
|
||||
{
|
||||
ec = rv.error();
|
||||
return;
|
||||
}
|
||||
apply(it, end,
|
||||
mp11::mp_size_t<Ir+1>{},
|
||||
mp11::mp_size_t<Iv+1>{});
|
||||
}
|
||||
|
||||
template<
|
||||
std::size_t Ir = 0,
|
||||
std::size_t Iv = 0>
|
||||
typename std::enable_if<
|
||||
Ir < 1 + sizeof...(Rn)>::type
|
||||
apply(
|
||||
char const*& it,
|
||||
char const* end,
|
||||
mp11::mp_size_t<Ir> const& ir = {},
|
||||
mp11::mp_size_t<Iv> const& iv = {}
|
||||
) noexcept
|
||||
{
|
||||
apply(it, end, ir, iv, is_void<Ir>{});
|
||||
}
|
||||
|
||||
struct deref
|
||||
{
|
||||
template<class R>
|
||||
auto
|
||||
operator()(R const& r) const ->
|
||||
decltype(*r)
|
||||
{
|
||||
return *r;
|
||||
}
|
||||
};
|
||||
|
||||
auto
|
||||
make_result() noexcept ->
|
||||
system::result<typename tuple_rule_t<
|
||||
R0, Rn...>::value_type>
|
||||
{
|
||||
if(ec.failed())
|
||||
return ec;
|
||||
return mp11::tuple_transform(
|
||||
deref{}, vn);
|
||||
}
|
||||
};
|
||||
|
||||
// returns a value_type
|
||||
template<class R0, class... Rn>
|
||||
struct parse_sequence<false, R0, Rn...>
|
||||
{
|
||||
using R = detail::tuple<R0, Rn...>;
|
||||
|
||||
using L = mp11::mp_list<
|
||||
typename R0::value_type,
|
||||
typename Rn::value_type...>;
|
||||
|
||||
using V = mp11::mp_first<
|
||||
mp11::mp_remove<
|
||||
mp11::mp_list<
|
||||
system::result<typename R0::value_type>,
|
||||
system::result<typename Rn::value_type>...>,
|
||||
system::result<void>>>;
|
||||
|
||||
template<std::size_t I>
|
||||
using is_void = std::is_same<
|
||||
mp11::mp_at_c<L, I>, void>;
|
||||
|
||||
R const& rn;
|
||||
V v;
|
||||
|
||||
explicit
|
||||
parse_sequence(
|
||||
R const& rn_) noexcept
|
||||
: rn(rn_)
|
||||
, v(system::error_code{})
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
apply(
|
||||
char const*&,
|
||||
char const*,
|
||||
...) const noexcept
|
||||
{
|
||||
}
|
||||
|
||||
// for system::result<void>
|
||||
template<
|
||||
std::size_t Ir,
|
||||
std::size_t Iv>
|
||||
BOOST_URL_NO_INLINE
|
||||
void
|
||||
apply(
|
||||
char const*& it,
|
||||
char const* end,
|
||||
mp11::mp_size_t<Ir> const&,
|
||||
mp11::mp_size_t<Iv> const&,
|
||||
mp11::mp_true const&)
|
||||
{
|
||||
system::result<void> rv =
|
||||
grammar::parse(
|
||||
it, end, get<Ir>(rn));
|
||||
if( !rv )
|
||||
{
|
||||
v = rv.error();
|
||||
return;
|
||||
}
|
||||
apply(it, end,
|
||||
mp11::mp_size_t<Ir+1>{},
|
||||
mp11::mp_size_t<Iv>{});
|
||||
}
|
||||
|
||||
template<
|
||||
std::size_t Ir,
|
||||
std::size_t Iv>
|
||||
void
|
||||
apply(
|
||||
char const*& it,
|
||||
char const* end,
|
||||
mp11::mp_size_t<Ir> const&,
|
||||
mp11::mp_size_t<Iv> const&,
|
||||
mp11::mp_false const&)
|
||||
{
|
||||
v = grammar::parse(
|
||||
it, end, get<Ir>(rn));
|
||||
if( !v )
|
||||
return;
|
||||
apply(it, end,
|
||||
mp11::mp_size_t<Ir+1>{},
|
||||
mp11::mp_size_t<Iv+1>{});
|
||||
}
|
||||
|
||||
template<
|
||||
std::size_t Ir = 0,
|
||||
std::size_t Iv = 0>
|
||||
typename std::enable_if<
|
||||
Ir < 1 + sizeof...(Rn)>::type
|
||||
apply(
|
||||
char const*& it,
|
||||
char const* end,
|
||||
mp11::mp_size_t<Ir> const& ir = {},
|
||||
mp11::mp_size_t<Iv> const& iv = {}
|
||||
) noexcept
|
||||
{
|
||||
apply(it, end, ir, iv, is_void<Ir>{});
|
||||
}
|
||||
|
||||
V
|
||||
make_result() noexcept
|
||||
{
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
template<
|
||||
class R0,
|
||||
class... Rn>
|
||||
auto
|
||||
tuple_rule_t<R0, Rn...>::
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const ->
|
||||
system::result<value_type>
|
||||
{
|
||||
detail::parse_sequence<
|
||||
IsList, R0, Rn...> t(this->get());
|
||||
t.apply(it, end);
|
||||
return t.make_result();
|
||||
}
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
//
|
||||
// Copyright (c) 2022 Alan de Freitas (alandefreitas at gmail dot 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_GRAMMAR_IMPL_UNSIGNED_RULE_HPP
|
||||
#define BOOST_URL_GRAMMAR_IMPL_UNSIGNED_RULE_HPP
|
||||
|
||||
#include <boost/url/grammar/error.hpp>
|
||||
#include <boost/url/grammar/digit_chars.hpp>
|
||||
#include <algorithm> // VFALCO grr..
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
template<class U>
|
||||
auto
|
||||
unsigned_rule<U>::
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end
|
||||
) const noexcept ->
|
||||
system::result<value_type>
|
||||
{
|
||||
if(it == end)
|
||||
{
|
||||
// end
|
||||
BOOST_URL_RETURN_EC(
|
||||
error::mismatch);
|
||||
}
|
||||
if(*it == '0')
|
||||
{
|
||||
++it;
|
||||
if( it == end ||
|
||||
! digit_chars(*it))
|
||||
{
|
||||
return U(0);
|
||||
}
|
||||
// bad leading zero
|
||||
BOOST_URL_RETURN_EC(
|
||||
error::invalid);
|
||||
}
|
||||
if(! digit_chars(*it))
|
||||
{
|
||||
// expected digit
|
||||
BOOST_URL_RETURN_EC(
|
||||
error::mismatch);
|
||||
}
|
||||
static constexpr U Digits10 =
|
||||
std::numeric_limits<
|
||||
U>::digits10;
|
||||
static constexpr U ten = 10;
|
||||
char const* safe_end;
|
||||
if(static_cast<std::size_t>(
|
||||
end - it) >= Digits10)
|
||||
safe_end = it + Digits10;
|
||||
else
|
||||
safe_end = end;
|
||||
U u = *it - '0';
|
||||
++it;
|
||||
while(it != safe_end &&
|
||||
digit_chars(*it))
|
||||
{
|
||||
char const dig = *it - '0';
|
||||
u = u * ten + dig;
|
||||
++it;
|
||||
}
|
||||
if( it != end &&
|
||||
digit_chars(*it))
|
||||
{
|
||||
static constexpr U Max = (
|
||||
std::numeric_limits<
|
||||
U>::max)();
|
||||
static constexpr
|
||||
auto div = (Max / ten);
|
||||
static constexpr
|
||||
char rem = (Max % ten);
|
||||
char const dig = *it - '0';
|
||||
if( u > div || (
|
||||
u == div && dig > rem))
|
||||
{
|
||||
// integer overflow
|
||||
BOOST_URL_RETURN_EC(
|
||||
error::invalid);
|
||||
}
|
||||
u = u * ten + dig;
|
||||
++it;
|
||||
if( it < end &&
|
||||
digit_chars(*it))
|
||||
{
|
||||
// integer overflow
|
||||
BOOST_URL_RETURN_EC(
|
||||
error::invalid);
|
||||
}
|
||||
}
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_IMPL_VARIANT_RULE_HPP
|
||||
#define BOOST_URL_GRAMMAR_IMPL_VARIANT_RULE_HPP
|
||||
|
||||
#include <boost/url/grammar/error.hpp>
|
||||
#include <boost/url/grammar/parse.hpp>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// must come first
|
||||
template<
|
||||
class R0,
|
||||
class... Rn,
|
||||
std::size_t I>
|
||||
auto
|
||||
parse_variant(
|
||||
char const*&,
|
||||
char const*,
|
||||
detail::tuple<
|
||||
R0, Rn...> const&,
|
||||
std::integral_constant<
|
||||
std::size_t, I> const&,
|
||||
std::false_type const&) ->
|
||||
system::result<variant<
|
||||
typename R0::value_type,
|
||||
typename Rn::value_type...>>
|
||||
{
|
||||
// no match
|
||||
BOOST_URL_RETURN_EC(
|
||||
error::mismatch);
|
||||
}
|
||||
|
||||
template<
|
||||
class R0,
|
||||
class... Rn,
|
||||
std::size_t I>
|
||||
auto
|
||||
parse_variant(
|
||||
char const*& it,
|
||||
char const* const end,
|
||||
detail::tuple<
|
||||
R0, Rn...> const& rn,
|
||||
std::integral_constant<
|
||||
std::size_t, I> const&,
|
||||
std::true_type const&) ->
|
||||
system::result<variant<
|
||||
typename R0::value_type,
|
||||
typename Rn::value_type...>>
|
||||
{
|
||||
auto const it0 = it;
|
||||
auto rv = parse(
|
||||
it, end, get<I>(rn));
|
||||
if( rv )
|
||||
return variant<
|
||||
typename R0::value_type,
|
||||
typename Rn::value_type...>{
|
||||
variant2::in_place_index_t<I>{}, *rv};
|
||||
it = it0;
|
||||
return parse_variant(
|
||||
it, end, rn,
|
||||
std::integral_constant<
|
||||
std::size_t, I+1>{},
|
||||
std::integral_constant<bool,
|
||||
((I + 1) < (1 +
|
||||
sizeof...(Rn)))>{});
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
template<class R0, class... Rn>
|
||||
auto
|
||||
variant_rule_t<R0, Rn...>::
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const ->
|
||||
system::result<value_type>
|
||||
{
|
||||
return detail::parse_variant(
|
||||
it, end, rn_,
|
||||
std::integral_constant<
|
||||
std::size_t, 0>{},
|
||||
std::true_type{});
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<class R0, class... Rn>
|
||||
auto
|
||||
constexpr
|
||||
variant_rule(
|
||||
R0 const& r0,
|
||||
Rn const&... rn) noexcept ->
|
||||
variant_rule_t<R0, Rn...>
|
||||
{
|
||||
return { r0, rn... };
|
||||
}
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_LITERAL_RULE_HPP
|
||||
#define BOOST_URL_GRAMMAR_LITERAL_RULE_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** Match a string literal exactly
|
||||
|
||||
If there is no more input, or if the
|
||||
end of the input is reached, and a prefix
|
||||
of the literal matches exactly, the error
|
||||
returned is @ref error::need_more.
|
||||
|
||||
@par Value Type
|
||||
@code
|
||||
using value_type = core::string_view;
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
Rules are used with the function @ref parse.
|
||||
@code
|
||||
system::result< core::string_view > rv = parse( "HTTP", literal_rule( "HTTP" ) );
|
||||
@endcode
|
||||
|
||||
@see
|
||||
@ref delim_rule,
|
||||
@ref parse.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
constexpr
|
||||
__implementation_defined__
|
||||
literal_rule( char const* s );
|
||||
#else
|
||||
class literal_rule
|
||||
{
|
||||
char const* s_ = nullptr;
|
||||
std::size_t n_ = 0;
|
||||
|
||||
constexpr
|
||||
static
|
||||
std::size_t
|
||||
len(char const* s) noexcept
|
||||
{
|
||||
return *s
|
||||
? 1 + len(s + 1)
|
||||
: 0;
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type = core::string_view;
|
||||
|
||||
constexpr
|
||||
explicit
|
||||
literal_rule(
|
||||
char const* s) noexcept
|
||||
: s_(s)
|
||||
, n_(len(s))
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_URL_DECL
|
||||
system::result<value_type>
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const noexcept;
|
||||
};
|
||||
#endif
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+402
@@ -0,0 +1,402 @@
|
||||
//
|
||||
// Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_LUT_CHARS_HPP
|
||||
#define BOOST_URL_GRAMMAR_LUT_CHARS_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/grammar/detail/charset.hpp>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
// Credit to Peter Dimov for ideas regarding
|
||||
// SIMD constexpr, and character set masks.
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
namespace detail {
|
||||
template<class T, class = void>
|
||||
struct is_pred : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_pred<T, void_t<
|
||||
decltype(
|
||||
std::declval<bool&>() =
|
||||
std::declval<T const&>().operator()(
|
||||
std::declval<char>())
|
||||
) > > : std::true_type
|
||||
{
|
||||
};
|
||||
} // detail
|
||||
#endif
|
||||
|
||||
/** A set of characters
|
||||
|
||||
The characters defined by instances of
|
||||
this set are provided upon construction.
|
||||
The `constexpr` implementation allows
|
||||
these to become compile-time constants.
|
||||
|
||||
@par Example
|
||||
Character sets are used with rules and the
|
||||
functions @ref find_if and @ref find_if_not.
|
||||
@code
|
||||
constexpr lut_chars vowel_chars = "AEIOU" "aeiou";
|
||||
|
||||
system::result< core::string_view > rv = parse( "Aiea", token_rule( vowel_chars ) );
|
||||
@endcode
|
||||
|
||||
@see
|
||||
@ref find_if,
|
||||
@ref find_if_not,
|
||||
@ref parse,
|
||||
@ref token_rule.
|
||||
*/
|
||||
class lut_chars
|
||||
{
|
||||
std::uint64_t mask_[4] = {};
|
||||
|
||||
constexpr
|
||||
static
|
||||
std::uint64_t
|
||||
lo(char c) noexcept
|
||||
{
|
||||
return static_cast<
|
||||
unsigned char>(c) & 3;
|
||||
}
|
||||
|
||||
constexpr
|
||||
static
|
||||
std::uint64_t
|
||||
hi(char c) noexcept
|
||||
{
|
||||
return 1ULL << (static_cast<
|
||||
unsigned char>(c) >> 2);
|
||||
}
|
||||
|
||||
constexpr
|
||||
static
|
||||
lut_chars
|
||||
construct(
|
||||
char const* s) noexcept
|
||||
{
|
||||
return *s
|
||||
? lut_chars(*s) +
|
||||
construct(s+1)
|
||||
: lut_chars();
|
||||
}
|
||||
|
||||
constexpr
|
||||
static
|
||||
lut_chars
|
||||
construct(
|
||||
unsigned char ch,
|
||||
bool b) noexcept
|
||||
{
|
||||
return b
|
||||
? lut_chars(ch)
|
||||
: lut_chars();
|
||||
}
|
||||
|
||||
template<class Pred>
|
||||
constexpr
|
||||
static
|
||||
lut_chars
|
||||
construct(
|
||||
Pred pred,
|
||||
unsigned char ch) noexcept
|
||||
{
|
||||
return ch == 255
|
||||
? construct(ch, pred(ch))
|
||||
: construct(ch, pred(ch)) +
|
||||
construct(pred, ch + 1);
|
||||
}
|
||||
|
||||
constexpr
|
||||
lut_chars() = default;
|
||||
|
||||
constexpr
|
||||
lut_chars(
|
||||
std::uint64_t m0,
|
||||
std::uint64_t m1,
|
||||
std::uint64_t m2,
|
||||
std::uint64_t m3) noexcept
|
||||
: mask_{ m0, m1, m2, m3 }
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
/** Constructor
|
||||
|
||||
This function constructs a character
|
||||
set which has as a single member,
|
||||
the character `ch`.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
constexpr lut_chars asterisk( '*' );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@param ch A character.
|
||||
*/
|
||||
constexpr
|
||||
lut_chars(char ch) noexcept
|
||||
: mask_ {
|
||||
lo(ch) == 0 ? hi(ch) : 0,
|
||||
lo(ch) == 1 ? hi(ch) : 0,
|
||||
lo(ch) == 2 ? hi(ch) : 0,
|
||||
lo(ch) == 3 ? hi(ch) : 0 }
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor
|
||||
|
||||
This function constructs a character
|
||||
set which has as members, all of the
|
||||
characters present in the null-terminated
|
||||
string `s`.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
constexpr lut_chars digits = "0123456789";
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `::strlen(s)`, or constant
|
||||
if `s` is a constant expression.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@param s A null-terminated string.
|
||||
*/
|
||||
constexpr
|
||||
lut_chars(
|
||||
char const* s) noexcept
|
||||
: lut_chars(construct(s))
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor.
|
||||
|
||||
This function constructs a character
|
||||
set which has as members, every value
|
||||
of `char ch` for which the expression
|
||||
`pred(ch)` returns `true`.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
struct is_digit
|
||||
{
|
||||
constexpr bool
|
||||
operator()(char c ) const noexcept
|
||||
{
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
};
|
||||
|
||||
constexpr lut_chars digits( is_digit{} );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `pred`, or constant if
|
||||
`pred(ch)` is a constant expression.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@param pred The function object to
|
||||
use for determining membership in
|
||||
the character set.
|
||||
*/
|
||||
template<class Pred
|
||||
#ifndef BOOST_URL_DOCS
|
||||
,class = typename std::enable_if<
|
||||
detail::is_pred<Pred>::value &&
|
||||
! std::is_base_of<
|
||||
lut_chars, Pred>::value>::type
|
||||
#endif
|
||||
>
|
||||
constexpr
|
||||
lut_chars(Pred const& pred) noexcept
|
||||
: lut_chars(
|
||||
construct(pred, 0))
|
||||
{
|
||||
}
|
||||
|
||||
/** Return true if ch is in the character set.
|
||||
|
||||
This function returns true if the
|
||||
character `ch` is in the set, otherwise
|
||||
it returns false.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@param ch The character to test.
|
||||
*/
|
||||
constexpr
|
||||
bool
|
||||
operator()(
|
||||
unsigned char ch) const noexcept
|
||||
{
|
||||
return mask_[lo(ch)] & hi(ch);
|
||||
}
|
||||
|
||||
/** Return the union of two character sets.
|
||||
|
||||
This function returns a new character
|
||||
set which contains all of the characters
|
||||
in `cs0` as well as all of the characters
|
||||
in `cs`.
|
||||
|
||||
@par Example
|
||||
This creates a character set which
|
||||
includes all letters and numbers
|
||||
@code
|
||||
constexpr lut_chars alpha_chars(
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz");
|
||||
|
||||
constexpr lut_chars alnum_chars = alpha_chars + "0123456789";
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@return The new character set.
|
||||
|
||||
@param cs0 A character to join
|
||||
|
||||
@param cs1 A character to join
|
||||
*/
|
||||
friend
|
||||
constexpr
|
||||
lut_chars
|
||||
operator+(
|
||||
lut_chars const& cs0,
|
||||
lut_chars const& cs1) noexcept
|
||||
{
|
||||
return lut_chars(
|
||||
cs0.mask_[0] | cs1.mask_[0],
|
||||
cs0.mask_[1] | cs1.mask_[1],
|
||||
cs0.mask_[2] | cs1.mask_[2],
|
||||
cs0.mask_[3] | cs1.mask_[3]);
|
||||
}
|
||||
|
||||
/** Return a new character set by subtracting
|
||||
|
||||
This function returns a new character
|
||||
set which is formed from all of the
|
||||
characters in `cs0` which are not in `cs`.
|
||||
|
||||
@par Example
|
||||
This statement declares a character set
|
||||
containing all the lowercase letters
|
||||
which are not vowels:
|
||||
@code
|
||||
constexpr lut_chars consonants = lut_chars("abcdefghijklmnopqrstuvwxyz") - "aeiou";
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@return The new character set.
|
||||
|
||||
@param cs0 A character set to join.
|
||||
|
||||
@param cs1 A character set to join.
|
||||
*/
|
||||
friend
|
||||
constexpr
|
||||
lut_chars
|
||||
operator-(
|
||||
lut_chars const& cs0,
|
||||
lut_chars const& cs1) noexcept
|
||||
{
|
||||
return lut_chars(
|
||||
cs0.mask_[0] & ~cs1.mask_[0],
|
||||
cs0.mask_[1] & ~cs1.mask_[1],
|
||||
cs0.mask_[2] & ~cs1.mask_[2],
|
||||
cs0.mask_[3] & ~cs1.mask_[3]);
|
||||
}
|
||||
|
||||
/** Return a new character set which is the complement of another character set.
|
||||
|
||||
This function returns a new character
|
||||
set which contains all of the characters
|
||||
that are not in `*this`.
|
||||
|
||||
@par Example
|
||||
This statement declares a character set
|
||||
containing everything but vowels:
|
||||
@code
|
||||
constexpr lut_chars not_vowels = ~lut_chars( "AEIOU" "aeiou" );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@return The new character set.
|
||||
*/
|
||||
constexpr
|
||||
lut_chars
|
||||
operator~() const noexcept
|
||||
{
|
||||
return lut_chars(
|
||||
~mask_[0],
|
||||
~mask_[1],
|
||||
~mask_[2],
|
||||
~mask_[3]
|
||||
);
|
||||
}
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
#ifdef BOOST_URL_USE_SSE2
|
||||
char const*
|
||||
find_if(
|
||||
char const* first,
|
||||
char const* last) const noexcept
|
||||
{
|
||||
return detail::find_if_pred(
|
||||
*this, first, last);
|
||||
}
|
||||
|
||||
char const*
|
||||
find_if_not(
|
||||
char const* first,
|
||||
char const* last) const noexcept
|
||||
{
|
||||
return detail::find_if_not_pred(
|
||||
*this, first, last);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_NOT_EMPTY_RULE_HPP
|
||||
#define BOOST_URL_GRAMMAR_NOT_EMPTY_RULE_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <boost/url/grammar/type_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** Match another rule, if the result is not empty
|
||||
|
||||
This adapts another rule such that
|
||||
when an empty string is successfully
|
||||
parsed, the result is an error.
|
||||
|
||||
@par Value Type
|
||||
@code
|
||||
using value_type = typename Rule::value_type;
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
Rules are used with the function @ref parse.
|
||||
@code
|
||||
system::result< decode_view > rv = parse( "Program%20Files",
|
||||
not_empty_rule( pct_encoded_rule( unreserved_chars ) ) );
|
||||
@endcode
|
||||
|
||||
@param r The rule to match
|
||||
|
||||
@see
|
||||
@ref parse,
|
||||
@ref pct_encoded_rule,
|
||||
@ref unreserved_chars.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<class Rule>
|
||||
constexpr
|
||||
__implementation_defined__
|
||||
not_empty_rule( Rule r );
|
||||
#else
|
||||
template<class R>
|
||||
struct not_empty_rule_t
|
||||
{
|
||||
using value_type =
|
||||
typename R::value_type;
|
||||
|
||||
auto
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const ->
|
||||
system::result<value_type>;
|
||||
|
||||
template<class R_>
|
||||
friend
|
||||
constexpr
|
||||
auto
|
||||
not_empty_rule(
|
||||
R_ const& r) ->
|
||||
not_empty_rule_t<R_>;
|
||||
|
||||
private:
|
||||
constexpr
|
||||
not_empty_rule_t(
|
||||
R const& r) noexcept
|
||||
: r_(r)
|
||||
{
|
||||
}
|
||||
|
||||
R r_;
|
||||
};
|
||||
|
||||
template<class Rule>
|
||||
auto
|
||||
constexpr
|
||||
not_empty_rule(
|
||||
Rule const& r) ->
|
||||
not_empty_rule_t<Rule>
|
||||
{
|
||||
// If you get a compile error here it
|
||||
// means that your rule does not meet
|
||||
// the type requirements. Please check
|
||||
// the documentation.
|
||||
static_assert(
|
||||
is_rule<Rule>::value,
|
||||
"Rule requirements not met");
|
||||
|
||||
return { r };
|
||||
}
|
||||
#endif
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#include <boost/url/grammar/impl/not_empty_rule.hpp>
|
||||
|
||||
#endif
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_OPTIONAL_RULE_HPP
|
||||
#define BOOST_URL_GRAMMAR_OPTIONAL_RULE_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/optional.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <boost/core/empty_value.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** Match a rule, or the empty string
|
||||
|
||||
Optional BNF elements are denoted with
|
||||
square brackets. If the specified rule
|
||||
returns any error it is treated as if
|
||||
the rule did not match.
|
||||
|
||||
@par Value Type
|
||||
@code
|
||||
using value_type = optional< typename Rule::value_type >;
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
Rules are used with the function @ref grammar::parse.
|
||||
@code
|
||||
system::result< optional< core::string_view > > rv = parse( "", optional_rule( token_rule( alpha_chars ) ) );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
optional = [ rule ]
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc5234#section-3.8"
|
||||
>3.8. Optional Sequence (rfc5234)</a>
|
||||
|
||||
@param r The rule to match
|
||||
|
||||
@see
|
||||
@ref alpha_chars,
|
||||
@ref parse,
|
||||
@ref optional,
|
||||
@ref token_rule.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<class Rule>
|
||||
constexpr
|
||||
__implementation_defined__
|
||||
optional_rule( Rule r ) noexcept;
|
||||
#else
|
||||
template<class Rule>
|
||||
struct optional_rule_t
|
||||
: private empty_value<Rule>
|
||||
{
|
||||
using value_type = boost::optional<
|
||||
typename Rule::value_type>;
|
||||
|
||||
system::result<value_type>
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const;
|
||||
|
||||
template<class R_>
|
||||
friend
|
||||
constexpr
|
||||
auto
|
||||
optional_rule(
|
||||
R_ const& r) ->
|
||||
optional_rule_t<R_>;
|
||||
|
||||
private:
|
||||
constexpr
|
||||
optional_rule_t(
|
||||
Rule const& r) noexcept
|
||||
: empty_value<Rule>(
|
||||
empty_init,
|
||||
r)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Rule>
|
||||
auto
|
||||
constexpr
|
||||
optional_rule(
|
||||
Rule const& r) ->
|
||||
optional_rule_t<Rule>
|
||||
{
|
||||
return { r };
|
||||
}
|
||||
#endif
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#include <boost/url/grammar/impl/optional_rule.hpp>
|
||||
|
||||
#endif
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_PARSE_HPP
|
||||
#define BOOST_URL_GRAMMAR_PARSE_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/url/grammar/type_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Parse a character buffer using a rule
|
||||
|
||||
@param it A pointer to the start. The
|
||||
caller's variable is changed to
|
||||
reflect the amount of input consumed.
|
||||
|
||||
@param end A pointer to the end.
|
||||
|
||||
@param r The rule to use
|
||||
|
||||
@return The parsed value upon success,
|
||||
otherwise an error.
|
||||
|
||||
@see
|
||||
@ref result.
|
||||
*/
|
||||
template<class Rule>
|
||||
system::result<typename Rule::value_type>
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end,
|
||||
Rule const& r);
|
||||
|
||||
/** Parse a character buffer using a rule
|
||||
|
||||
This function parses a complete string into
|
||||
the specified sequence of rules. If the
|
||||
string is not completely consumed, an
|
||||
error is returned instead.
|
||||
|
||||
@param s The input string
|
||||
|
||||
@param r The rule to use
|
||||
|
||||
@return The parsed value upon success,
|
||||
otherwise an error.
|
||||
|
||||
@see
|
||||
@ref result.
|
||||
*/
|
||||
template<class Rule>
|
||||
system::result<typename Rule::value_type>
|
||||
parse(
|
||||
core::string_view s,
|
||||
Rule const& r);
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
namespace detail {
|
||||
|
||||
template<class Rule>
|
||||
struct rule_ref
|
||||
{
|
||||
Rule const& r_;
|
||||
|
||||
using value_type =
|
||||
typename Rule::value_type;
|
||||
|
||||
system::result<value_type>
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const
|
||||
{
|
||||
return r_.parse(it, end);
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
#endif
|
||||
|
||||
/** Return a reference to a rule
|
||||
|
||||
This function returns a rule which
|
||||
references the specified object. This is
|
||||
used to reduce the number of bytes of
|
||||
storage (`sizeof`) required by a combinator
|
||||
when it stores a copy of the object.
|
||||
<br>
|
||||
Ownership of the object is not transferred;
|
||||
the caller is responsible for ensuring the
|
||||
lifetime of the object is extended until it
|
||||
is no longer referenced. For best results,
|
||||
`ref` should only be used with compile-time
|
||||
constants.
|
||||
|
||||
@param r The rule to use
|
||||
*/
|
||||
template<class Rule>
|
||||
constexpr
|
||||
#ifdef BOOST_URL_DOCS
|
||||
__implementation_defined__
|
||||
#else
|
||||
typename std::enable_if<
|
||||
is_rule<Rule>::value &&
|
||||
! std::is_same<Rule,
|
||||
detail::rule_ref<Rule> >::value,
|
||||
detail::rule_ref<Rule> >::type
|
||||
#endif
|
||||
ref(Rule const& r) noexcept
|
||||
{
|
||||
return detail::rule_ref<
|
||||
Rule>{r};
|
||||
}
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
// If you get a compile error here it
|
||||
// means you called ref with something
|
||||
// that is not a CharSet or Rule!
|
||||
constexpr
|
||||
void
|
||||
ref(...) = delete;
|
||||
#endif
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#include <boost/url/grammar/impl/parse.hpp>
|
||||
|
||||
#endif
|
||||
+602
@@ -0,0 +1,602 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_RANGE_RULE_HPP
|
||||
#define BOOST_URL_GRAMMAR_RANGE_RULE_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/error.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/url/grammar/parse.hpp>
|
||||
#include <boost/url/grammar/type_traits.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
#include <stddef.h> // ::max_align_t
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** A forward range of parsed elements
|
||||
|
||||
Objects of this type are forward ranges
|
||||
returned when parsing using the
|
||||
@ref range_rule.
|
||||
Iteration is performed by re-parsing the
|
||||
underlying character buffer. Ownership
|
||||
of the buffer is not transferred; the
|
||||
caller is responsible for ensuring that
|
||||
the lifetime of the buffer extends until
|
||||
it is no longer referenced by the range.
|
||||
|
||||
@note
|
||||
|
||||
The implementation may use temporary,
|
||||
recycled storage for type-erasure. Objects
|
||||
of type `range` are intended to be used
|
||||
ephemerally. That is, for short durations
|
||||
such as within a function scope. If it is
|
||||
necessary to store the range for a long
|
||||
period of time or with static storage
|
||||
duration, it is necessary to copy the
|
||||
contents to an object of a different type.
|
||||
|
||||
@tparam T The value type of the range
|
||||
|
||||
@see
|
||||
@ref parse,
|
||||
@ref range_rule.
|
||||
*/
|
||||
template<class T>
|
||||
class range
|
||||
{
|
||||
// buffer size for type-erased rule
|
||||
static constexpr
|
||||
std::size_t BufferSize = 128;
|
||||
|
||||
struct small_buffer
|
||||
{
|
||||
alignas(alignof(::max_align_t))
|
||||
unsigned char buf[BufferSize];
|
||||
|
||||
void const* addr() const noexcept
|
||||
{
|
||||
return buf;
|
||||
}
|
||||
|
||||
void* addr() noexcept
|
||||
{
|
||||
return buf;
|
||||
}
|
||||
};
|
||||
|
||||
small_buffer sb_;
|
||||
core::string_view s_;
|
||||
std::size_t n_ = 0;
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
struct any_rule;
|
||||
|
||||
template<class R, bool>
|
||||
struct impl1;
|
||||
|
||||
template<
|
||||
class R0, class R1, bool>
|
||||
struct impl2;
|
||||
|
||||
template<
|
||||
class R0, class R1>
|
||||
friend struct range_rule_t;
|
||||
|
||||
any_rule&
|
||||
get() noexcept
|
||||
{
|
||||
return *reinterpret_cast<
|
||||
any_rule*>(sb_.addr());
|
||||
}
|
||||
|
||||
any_rule const&
|
||||
get() const noexcept
|
||||
{
|
||||
return *reinterpret_cast<
|
||||
any_rule const*>(
|
||||
sb_.addr());
|
||||
}
|
||||
|
||||
template<class R>
|
||||
range(
|
||||
core::string_view s,
|
||||
std::size_t n,
|
||||
R const& r);
|
||||
|
||||
template<
|
||||
class R0, class R1>
|
||||
range(
|
||||
core::string_view s,
|
||||
std::size_t n,
|
||||
R0 const& first,
|
||||
R1 const& next);
|
||||
|
||||
public:
|
||||
/** The type of each element of the range
|
||||
*/
|
||||
using value_type = T;
|
||||
|
||||
/** The type of each element of the range
|
||||
*/
|
||||
using reference = T const&;
|
||||
|
||||
/** The type of each element of the range
|
||||
*/
|
||||
using const_reference = T const&;
|
||||
|
||||
/** Provided for compatibility, unused
|
||||
*/
|
||||
using pointer = void const*;
|
||||
|
||||
/** The type used to represent unsigned integers
|
||||
*/
|
||||
using size_type = std::size_t;
|
||||
|
||||
/** The type used to represent signed integers
|
||||
*/
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
/** A constant, forward iterator to elements of the range
|
||||
*/
|
||||
class iterator;
|
||||
|
||||
/** A constant, forward iterator to elements of the range
|
||||
*/
|
||||
using const_iterator = iterator;
|
||||
|
||||
/** Destructor
|
||||
*/
|
||||
~range();
|
||||
|
||||
/** Constructor
|
||||
|
||||
Default-constructed ranges have
|
||||
zero elements.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
range() noexcept;
|
||||
|
||||
/** Constructor
|
||||
|
||||
The new range references the
|
||||
same underlying character buffer.
|
||||
Ownership is not transferred; the
|
||||
caller is responsible for ensuring
|
||||
that the lifetime of the buffer
|
||||
extends until it is no longer
|
||||
referenced. The moved-from object
|
||||
becomes as if default-constructed.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
range(range&&) noexcept;
|
||||
|
||||
/** Constructor
|
||||
|
||||
The copy references the same
|
||||
underlying character buffer.
|
||||
Ownership is not transferred; the
|
||||
caller is responsible for ensuring
|
||||
that the lifetime of the buffer
|
||||
extends until it is no longer
|
||||
referenced.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
range(range const&) noexcept;
|
||||
|
||||
/** Constructor
|
||||
|
||||
After the move, this references the
|
||||
same underlying character buffer. Ownership
|
||||
is not transferred; the caller is responsible
|
||||
for ensuring that the lifetime of the buffer
|
||||
extends until it is no longer referenced.
|
||||
The moved-from object becomes as if
|
||||
default-constructed.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
range&
|
||||
operator=(range&&) noexcept;
|
||||
|
||||
/** Assignment
|
||||
|
||||
The copy references the same
|
||||
underlying character buffer.
|
||||
Ownership is not transferred; the
|
||||
caller is responsible for ensuring
|
||||
that the lifetime of the buffer
|
||||
extends until it is no longer
|
||||
referenced.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
range&
|
||||
operator=(range const&) noexcept;
|
||||
|
||||
/** Return an iterator to the beginning
|
||||
*/
|
||||
iterator begin() const noexcept;
|
||||
|
||||
/** Return an iterator to the end
|
||||
*/
|
||||
iterator end() const noexcept;
|
||||
|
||||
/** Return true if the range is empty
|
||||
*/
|
||||
bool
|
||||
empty() const noexcept
|
||||
{
|
||||
return n_ == 0;
|
||||
}
|
||||
|
||||
/** Return the number of elements in the range
|
||||
*/
|
||||
std::size_t
|
||||
size() const noexcept
|
||||
{
|
||||
return n_;
|
||||
}
|
||||
|
||||
/** Return the matching part of the string
|
||||
*/
|
||||
core::string_view
|
||||
string() const noexcept
|
||||
{
|
||||
return s_;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
template<
|
||||
class R0,
|
||||
class R1 = void>
|
||||
struct range_rule_t;
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Match a repeating number of elements
|
||||
|
||||
Elements are matched using the passed rule.
|
||||
<br>
|
||||
Normally when the rule returns an error,
|
||||
the range ends and the input is rewound to
|
||||
one past the last character that matched
|
||||
successfully. However, if the rule returns
|
||||
the special value @ref error::end_of_range, the
|
||||
input is not rewound. This allows for rules
|
||||
which consume input without producing
|
||||
elements in the range. For example, to
|
||||
relax the grammar for a comma-delimited
|
||||
list by allowing extra commas in between
|
||||
elements.
|
||||
|
||||
@par Value Type
|
||||
@code
|
||||
using value_type = range< typename Rule::value_type >;
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
Rules are used with the function @ref parse.
|
||||
@code
|
||||
// range = 1*( ";" token )
|
||||
|
||||
system::result< range<core::string_view> > rv = parse( ";alpha;xray;charlie",
|
||||
range_rule(
|
||||
tuple_rule(
|
||||
squelch( delim_rule( ';' ) ),
|
||||
token_rule( alpha_chars ) ),
|
||||
1 ) );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
range = <N>*<M>next
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc5234#section-3.6"
|
||||
>3.6. Variable Repetition (rfc5234)</a>
|
||||
|
||||
@param next The rule to use for matching
|
||||
each element. The range extends until this
|
||||
rule returns an error.
|
||||
|
||||
@param N The minimum number of elements for
|
||||
the range to be valid. If omitted, this
|
||||
defaults to zero.
|
||||
|
||||
@param M The maximum number of elements for
|
||||
the range to be valid. If omitted, this
|
||||
defaults to unlimited.
|
||||
|
||||
@see
|
||||
@ref alpha_chars,
|
||||
@ref delim_rule,
|
||||
@ref error::end_of_range,
|
||||
@ref parse,
|
||||
@ref range,
|
||||
@ref tuple_rule,
|
||||
@ref squelch.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<class Rule>
|
||||
constexpr
|
||||
__implementation_defined__
|
||||
range_rule(
|
||||
Rule next,
|
||||
std::size_t N = 0,
|
||||
std::size_t M =
|
||||
std::size_t(-1)) noexcept;
|
||||
#else
|
||||
template<class R>
|
||||
struct range_rule_t<R>
|
||||
{
|
||||
using value_type =
|
||||
range<typename R::value_type>;
|
||||
|
||||
system::result<value_type>
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const;
|
||||
|
||||
private:
|
||||
constexpr
|
||||
range_rule_t(
|
||||
R const& next,
|
||||
std::size_t N,
|
||||
std::size_t M) noexcept
|
||||
: next_(next)
|
||||
, N_(N)
|
||||
, M_(M)
|
||||
{
|
||||
}
|
||||
|
||||
template<class R_>
|
||||
friend
|
||||
constexpr
|
||||
range_rule_t<R_>
|
||||
range_rule(
|
||||
R_ const& next,
|
||||
std::size_t N,
|
||||
std::size_t M) noexcept;
|
||||
|
||||
R const next_;
|
||||
std::size_t N_;
|
||||
std::size_t M_;
|
||||
};
|
||||
|
||||
template<class Rule>
|
||||
constexpr
|
||||
range_rule_t<Rule>
|
||||
range_rule(
|
||||
Rule const& next,
|
||||
std::size_t N = 0,
|
||||
std::size_t M =
|
||||
std::size_t(-1)) noexcept
|
||||
{
|
||||
// If you get a compile error here it
|
||||
// means that your rule does not meet
|
||||
// the type requirements. Please check
|
||||
// the documentation.
|
||||
static_assert(
|
||||
is_rule<Rule>::value,
|
||||
"Rule requirements not met");
|
||||
|
||||
return range_rule_t<Rule>{
|
||||
next, N, M};
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Match a repeating number of elements
|
||||
|
||||
Two rules are used for match. The rule
|
||||
`first` is used for matching the first
|
||||
element, while the `next` rule is used
|
||||
to match every subsequent element.
|
||||
<br>
|
||||
Normally when the rule returns an error,
|
||||
the range ends and the input is rewound to
|
||||
one past the last character that matched
|
||||
successfully. However, if the rule returns
|
||||
the special value @ref error::end_of_range, the
|
||||
input is not rewound. This allows for rules
|
||||
which consume input without producing
|
||||
elements in the range. For example, to
|
||||
relax the grammar for a comma-delimited
|
||||
list by allowing extra commas in between
|
||||
elements.
|
||||
|
||||
@par Value Type
|
||||
@code
|
||||
using value_type = range< typename Rule::value_type >;
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
Rules are used with the function @ref parse.
|
||||
@code
|
||||
// range = [ token ] *( "," token )
|
||||
|
||||
system::result< range< core::string_view > > rv = parse( "whiskey,tango,foxtrot",
|
||||
range_rule(
|
||||
token_rule( alpha_chars ), // first
|
||||
tuple_rule( // next
|
||||
squelch( delim_rule(',') ),
|
||||
token_rule( alpha_chars ) ) ) );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
range = <1>*<1>first
|
||||
/ first <N-1>*<M-1>next
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc5234#section-3.6"
|
||||
>3.6. Variable Repetition (rfc5234)</a>
|
||||
|
||||
@param first The rule to use for matching
|
||||
the first element. If this rule returns
|
||||
an error, the range is empty.
|
||||
|
||||
@param next The rule to use for matching
|
||||
each subsequent element. The range extends
|
||||
until this rule returns an error.
|
||||
|
||||
@param N The minimum number of elements for
|
||||
the range to be valid. If omitted, this
|
||||
defaults to zero.
|
||||
|
||||
@param M The maximum number of elements for
|
||||
the range to be valid. If omitted, this
|
||||
defaults to unlimited.
|
||||
|
||||
@see
|
||||
@ref alpha_chars,
|
||||
@ref delim_rule,
|
||||
@ref error::end_of_range,
|
||||
@ref parse,
|
||||
@ref range,
|
||||
@ref tuple_rule,
|
||||
@ref squelch.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<
|
||||
class Rule1, class Rule2>
|
||||
constexpr
|
||||
__implementation_defined__
|
||||
range_rule(
|
||||
Rule1 first,
|
||||
Rule2 next,
|
||||
std::size_t N = 0,
|
||||
std::size_t M =
|
||||
std::size_t(-1)) noexcept;
|
||||
#else
|
||||
template<class R0, class R1>
|
||||
struct range_rule_t
|
||||
{
|
||||
using value_type =
|
||||
range<typename R0::value_type>;
|
||||
|
||||
system::result<value_type>
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const;
|
||||
|
||||
private:
|
||||
constexpr
|
||||
range_rule_t(
|
||||
R0 const& first,
|
||||
R1 const& next,
|
||||
std::size_t N,
|
||||
std::size_t M) noexcept
|
||||
: first_(first)
|
||||
, next_(next)
|
||||
, N_(N)
|
||||
, M_(M)
|
||||
{
|
||||
}
|
||||
|
||||
template<
|
||||
class R0_, class R1_>
|
||||
friend
|
||||
constexpr
|
||||
auto
|
||||
range_rule(
|
||||
R0_ const& first,
|
||||
R1_ const& next,
|
||||
std::size_t N,
|
||||
std::size_t M) noexcept ->
|
||||
#if 1
|
||||
typename std::enable_if<
|
||||
! std::is_integral<R1_>::value,
|
||||
range_rule_t<R0_, R1_>>::type;
|
||||
#else
|
||||
range_rule_t<R0_, R1_>;
|
||||
#endif
|
||||
|
||||
R0 const first_;
|
||||
R1 const next_;
|
||||
std::size_t N_;
|
||||
std::size_t M_;
|
||||
};
|
||||
|
||||
template<
|
||||
class Rule1, class Rule2>
|
||||
constexpr
|
||||
auto
|
||||
range_rule(
|
||||
Rule1 const& first,
|
||||
Rule2 const& next,
|
||||
std::size_t N = 0,
|
||||
std::size_t M =
|
||||
std::size_t(-1)) noexcept ->
|
||||
#if 1
|
||||
typename std::enable_if<
|
||||
! std::is_integral<Rule2>::value,
|
||||
range_rule_t<Rule1, Rule2>>::type
|
||||
#else
|
||||
range_rule_t<Rule1, Rule2>
|
||||
#endif
|
||||
{
|
||||
// If you get a compile error here it
|
||||
// means that your rule does not meet
|
||||
// the type requirements. Please check
|
||||
// the documentation.
|
||||
static_assert(
|
||||
is_rule<Rule1>::value,
|
||||
"Rule requirements not met");
|
||||
static_assert(
|
||||
is_rule<Rule2>::value,
|
||||
"Rule requirements not met");
|
||||
|
||||
// If you get a compile error here it
|
||||
// means that your rules do not have
|
||||
// the exact same value_type. Please
|
||||
// check the documentation.
|
||||
static_assert(
|
||||
std::is_same<
|
||||
typename Rule1::value_type,
|
||||
typename Rule2::value_type>::value,
|
||||
"Rule requirements not met");
|
||||
|
||||
return range_rule_t<Rule1, Rule2>{
|
||||
first, next, N, M};
|
||||
}
|
||||
#endif
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#include <boost/url/grammar/impl/range_rule.hpp>
|
||||
|
||||
#endif
|
||||
+510
@@ -0,0 +1,510 @@
|
||||
//
|
||||
// Copyright (c) 2022 Vinnie Falco (vinnie.falco@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_GRAMMAR_RECYCLED_HPP
|
||||
#define BOOST_URL_GRAMMAR_RECYCLED_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/grammar/detail/recycled.hpp>
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <stddef.h> // ::max_align_t
|
||||
|
||||
#if !defined(BOOST_URL_DISABLE_THREADS)
|
||||
# include <mutex>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** Provides an aligned storage buffer aligned for T
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<class T>
|
||||
struct aligned_storage
|
||||
{
|
||||
/** Return a pointer to the aligned storage area
|
||||
*/
|
||||
void* addr() noexcept;
|
||||
|
||||
/** Return a pointer to the aligned storage area
|
||||
*/
|
||||
void const* addr() const noexcept;
|
||||
};
|
||||
#else
|
||||
template<class T>
|
||||
using aligned_storage =
|
||||
detail::aligned_storage_impl<
|
||||
detail::nearest_pow2(sizeof(T), 64),
|
||||
(alignof(::max_align_t) > alignof(T)) ?
|
||||
alignof(::max_align_t) : alignof(T)>;
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** A thread-safe collection of instances of T
|
||||
|
||||
Instances of this type may be used to control
|
||||
where recycled instances of T come from when
|
||||
used with @ref recycled_ptr.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
static recycled< std::string > bin;
|
||||
|
||||
recycled_ptr< std::string > ps( bin );
|
||||
|
||||
// Put the string into a known state
|
||||
ps->clear();
|
||||
@endcode
|
||||
|
||||
@see
|
||||
@ref recycled_ptr.
|
||||
*/
|
||||
template<class T>
|
||||
class recycled
|
||||
{
|
||||
public:
|
||||
/** Destructor
|
||||
|
||||
All recycled instances of T are destroyed.
|
||||
Undefined behavior results if there are
|
||||
any @ref recycled_ptr which reference
|
||||
this recycle bin.
|
||||
*/
|
||||
~recycled();
|
||||
|
||||
/** Constructor
|
||||
*/
|
||||
constexpr recycled() = default;
|
||||
|
||||
private:
|
||||
template<class>
|
||||
friend class recycled_ptr;
|
||||
|
||||
struct U
|
||||
{
|
||||
T t;
|
||||
U* next = nullptr;
|
||||
|
||||
#if !defined(BOOST_URL_DISABLE_THREADS)
|
||||
std::atomic<
|
||||
std::size_t> refs;
|
||||
#else
|
||||
std::size_t refs;
|
||||
#endif
|
||||
|
||||
|
||||
U()
|
||||
: refs{1}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct report;
|
||||
|
||||
U* acquire();
|
||||
void release(U* u) noexcept;
|
||||
|
||||
U* head_ = nullptr;
|
||||
|
||||
#if !defined(BOOST_URL_DISABLE_THREADS)
|
||||
std::mutex m_;
|
||||
#endif
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** A pointer to shared instance of T
|
||||
|
||||
This is a smart pointer container which can
|
||||
acquire shared ownership of an instance of
|
||||
`T` upon or after construction. The instance
|
||||
is guaranteed to be in a valid, but unknown
|
||||
state. Every recycled pointer references
|
||||
a valid recycle bin.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
static recycled< std::string > bin;
|
||||
|
||||
recycled_ptr< std::string > ps( bin );
|
||||
|
||||
// Put the string into a known state
|
||||
ps->clear();
|
||||
@endcode
|
||||
|
||||
@tparam T the type of object to
|
||||
acquire, which must be
|
||||
<em>DefaultConstructible</em>.
|
||||
*/
|
||||
template<class T>
|
||||
class recycled_ptr
|
||||
{
|
||||
// T must be default constructible!
|
||||
static_assert(
|
||||
std::is_default_constructible<T>::value,
|
||||
"T must be DefaultConstructible");
|
||||
|
||||
friend class recycled<T>;
|
||||
|
||||
using B = recycled<T>;
|
||||
using U = typename B::U;
|
||||
|
||||
B* bin_ = nullptr;
|
||||
U* p_ = nullptr;
|
||||
|
||||
public:
|
||||
/** Destructor
|
||||
|
||||
If this is not empty, shared ownership
|
||||
of the pointee is released. If this was
|
||||
the last reference, the object is
|
||||
returned to the original recycle bin.
|
||||
|
||||
@par Effects
|
||||
@code
|
||||
this->release();
|
||||
@endcode
|
||||
*/
|
||||
~recycled_ptr();
|
||||
|
||||
/** Constructor
|
||||
|
||||
Upon construction, this acquires
|
||||
exclusive access to an object of type
|
||||
`T` which is either recycled from the
|
||||
specified bin, or newly allocated.
|
||||
The object is in an unknown but
|
||||
valid state.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
static recycled< std::string > bin;
|
||||
|
||||
recycled_ptr< std::string > ps( bin );
|
||||
|
||||
// Put the string into a known state
|
||||
ps->clear();
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
&this->bin() == &bin && ! this->empty()
|
||||
@endcode
|
||||
|
||||
@param bin The recycle bin to use
|
||||
|
||||
@see
|
||||
@ref recycled.
|
||||
*/
|
||||
explicit
|
||||
recycled_ptr(recycled<T>& bin);
|
||||
|
||||
/** Constructor
|
||||
|
||||
After construction, this is empty and
|
||||
refers to the specified recycle bin.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
static recycled< std::string > bin;
|
||||
|
||||
recycled_ptr< std::string > ps( bin, nullptr );
|
||||
|
||||
// Acquire a string and put it into a known state
|
||||
ps->acquire();
|
||||
ps->clear();
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
&this->bin() == &bin && this->empty()
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@param bin The recycle bin to use
|
||||
|
||||
@see
|
||||
@ref acquire,
|
||||
@ref recycled,
|
||||
@ref release.
|
||||
*/
|
||||
recycled_ptr(
|
||||
recycled<T>& bin,
|
||||
std::nullptr_t) noexcept;
|
||||
|
||||
/** Constructor
|
||||
|
||||
Upon construction, this acquires
|
||||
exclusive access to an object of type
|
||||
`T` which is either recycled from a
|
||||
global recycle bin, or newly allocated.
|
||||
The object is in an unknown but
|
||||
valid state.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
recycled_ptr< std::string > ps;
|
||||
|
||||
// Put the string into a known state
|
||||
ps->clear();
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
&this->bin() != nullptr && ! this->empty()
|
||||
@endcode
|
||||
|
||||
@see
|
||||
@ref recycled.
|
||||
*/
|
||||
recycled_ptr();
|
||||
|
||||
/** Constructor
|
||||
|
||||
After construction, this is empty
|
||||
and refers to a global recycle bin.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
recycled_ptr< std::string > ps( nullptr );
|
||||
|
||||
// Acquire a string and put it into a known state
|
||||
ps->acquire();
|
||||
ps->clear();
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
&this->bin() != nullptr && this->empty()
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@see
|
||||
@ref acquire,
|
||||
@ref recycled,
|
||||
@ref release.
|
||||
*/
|
||||
recycled_ptr(
|
||||
std::nullptr_t) noexcept;
|
||||
|
||||
/** Constructor
|
||||
|
||||
If `other` references an object, the
|
||||
newly constructed pointer acquires
|
||||
shared ownership. Otherwise this is
|
||||
empty. The new pointer references
|
||||
the same recycle bin as `other`.
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
&this->bin() == &other->bin() && this->get() == other.get()
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@param other The pointer to copy
|
||||
*/
|
||||
recycled_ptr(
|
||||
recycled_ptr const& other) noexcept;
|
||||
|
||||
/** Constructor
|
||||
|
||||
If `other` references an object,
|
||||
ownership is transferred including
|
||||
a reference to the recycle bin. After
|
||||
the move, the moved-from object is empty.
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
&this->bin() == &other->bin() && ! this->empty() && other.empty()
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@param other The pointer to move from
|
||||
*/
|
||||
recycled_ptr(
|
||||
recycled_ptr&& other) noexcept;
|
||||
|
||||
/** Assignment
|
||||
|
||||
If `other` references an object,
|
||||
ownership is transferred including
|
||||
a reference to the recycle bin. After
|
||||
the move, the moved-from object is empty.
|
||||
|
||||
@par Effects
|
||||
@code
|
||||
this->release()
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
&this->bin() == &other->bin()
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@param other The pointer to move from
|
||||
*/
|
||||
recycled_ptr&
|
||||
operator=(
|
||||
recycled_ptr&& other) noexcept;
|
||||
|
||||
/** Assignment
|
||||
|
||||
If `other` references an object,
|
||||
this acquires shared ownership and
|
||||
references the same recycle bin as
|
||||
`other`. The previous object if any
|
||||
is released.
|
||||
|
||||
@par Effects
|
||||
@code
|
||||
this->release()
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
&this->bin() == &other->bin() && this->get() == other.get()
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@param other The pointer to copy from
|
||||
*/
|
||||
recycled_ptr&
|
||||
operator=(
|
||||
recycled_ptr const& other) noexcept;
|
||||
|
||||
/** Return true if this does not reference an object
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
bool
|
||||
empty() const noexcept
|
||||
{
|
||||
return p_ == nullptr;
|
||||
}
|
||||
|
||||
/** Return true if this references an object
|
||||
|
||||
@par Effects
|
||||
@code
|
||||
return ! this->empty();
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
explicit
|
||||
operator bool() const noexcept
|
||||
{
|
||||
return p_ != nullptr;
|
||||
}
|
||||
|
||||
/** Return the referenced recycle bin
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
recycled<T>&
|
||||
bin() const noexcept
|
||||
{
|
||||
return *bin_;
|
||||
}
|
||||
|
||||
/** Return the referenced object
|
||||
|
||||
If this is empty, `nullptr` is returned.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
T* get() const noexcept
|
||||
{
|
||||
return &p_->t;
|
||||
}
|
||||
|
||||
/** Return the referenced object
|
||||
|
||||
If this is empty, `nullptr` is returned.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
T* operator->() const noexcept
|
||||
{
|
||||
return get();
|
||||
}
|
||||
|
||||
/** Return the referenced object
|
||||
|
||||
@par Preconditions
|
||||
@code
|
||||
not this->empty()
|
||||
@endcode
|
||||
*/
|
||||
T& operator*() const noexcept
|
||||
{
|
||||
return *get();
|
||||
}
|
||||
|
||||
/** Return the referenced object
|
||||
|
||||
If this references an object, it is
|
||||
returned. Otherwise, exclusive ownership
|
||||
of a new object of type `T` is acquired
|
||||
and returned.
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
not this->empty()
|
||||
@endcode
|
||||
*/
|
||||
T& acquire();
|
||||
|
||||
/** Release the referenced object
|
||||
|
||||
If this references an object, it is
|
||||
released to the referenced recycle bin.
|
||||
The pointer continues to reference
|
||||
the same recycle bin.
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->empty()
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
void release() noexcept;
|
||||
};
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#include <boost/url/grammar/impl/recycled.hpp>
|
||||
|
||||
#endif
|
||||
+347
@@ -0,0 +1,347 @@
|
||||
//
|
||||
// Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_STRING_TOKEN_HPP
|
||||
#define BOOST_URL_GRAMMAR_STRING_TOKEN_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/url/detail/except.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace string_token {
|
||||
|
||||
/** Base class for string tokens, and algorithm parameters
|
||||
|
||||
This abstract interface provides a means
|
||||
for an algorithm to generically obtain a
|
||||
modifiable, contiguous character buffer
|
||||
of prescribed size. As the author of an
|
||||
algorithm simply declare an rvalue
|
||||
reference as a parameter type.
|
||||
|
||||
<br>
|
||||
|
||||
Instances of this type are intended only
|
||||
to be used once and then destroyed.
|
||||
|
||||
@par Example
|
||||
The declared function accepts any
|
||||
temporary instance of `arg` to be
|
||||
used for writing:
|
||||
@code
|
||||
void algorithm( string_token::arg&& dest );
|
||||
@endcode
|
||||
|
||||
To implement the interface for your type
|
||||
or use-case, derive from the class and
|
||||
implement the prepare function.
|
||||
*/
|
||||
struct arg
|
||||
{
|
||||
/** Return a modifiable character buffer
|
||||
|
||||
This function attempts to obtain a
|
||||
character buffer with space for at
|
||||
least `n` characters. Upon success,
|
||||
a pointer to the beginning of the
|
||||
buffer is returned. Ownership is not
|
||||
transferred; the caller should not
|
||||
attempt to free the storage. The
|
||||
buffer shall remain valid until
|
||||
`this` is destroyed.
|
||||
|
||||
@note
|
||||
This function may only be called once.
|
||||
After invoking the function, the only
|
||||
valid operation is destruction.
|
||||
*/
|
||||
virtual char* prepare(std::size_t n) = 0;
|
||||
|
||||
// prevent misuse
|
||||
virtual ~arg() = default;
|
||||
arg() = default;
|
||||
arg(arg&&) = default;
|
||||
arg(arg const&) = delete;
|
||||
arg& operator=(arg&&) = delete;
|
||||
arg& operator=(arg const&) = delete;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Metafunction returning true if T is a StringToken
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<class T>
|
||||
using is_token = __see_below__;
|
||||
#else
|
||||
template<class T, class = void>
|
||||
struct is_token : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_token<T, void_t<
|
||||
decltype(std::declval<T&>().prepare(
|
||||
std::declval<std::size_t>())),
|
||||
decltype(std::declval<T&>().result())
|
||||
> > : std::integral_constant<bool,
|
||||
std::is_convertible<decltype(
|
||||
std::declval<T&>().result()),
|
||||
typename T::result_type>::value &&
|
||||
std::is_same<decltype(
|
||||
std::declval<T&>().prepare(0)),
|
||||
char*>::value &&
|
||||
std::is_base_of<arg, T>::value &&
|
||||
std::is_convertible<T const volatile*,
|
||||
arg const volatile*>::value
|
||||
>
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** A token for returning a plain string
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
using return_string = __implementation_defined__;
|
||||
#else
|
||||
struct return_string
|
||||
: arg
|
||||
{
|
||||
using result_type = std::string;
|
||||
|
||||
char*
|
||||
prepare(std::size_t n) override
|
||||
{
|
||||
s_.resize(n);
|
||||
return &s_[0];
|
||||
}
|
||||
|
||||
result_type
|
||||
result() noexcept
|
||||
{
|
||||
return std::move(s_);
|
||||
}
|
||||
|
||||
private:
|
||||
result_type s_;
|
||||
};
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** A token for appending to a plain string
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<
|
||||
class Allocator =
|
||||
std::allocator<char>>
|
||||
__implementation_defined__
|
||||
append_to(
|
||||
std::basic_string<
|
||||
char,
|
||||
std::char_traits<char>,
|
||||
Allocator>& s);
|
||||
#else
|
||||
template<class Alloc>
|
||||
struct append_to_t
|
||||
: arg
|
||||
{
|
||||
using string_type = std::basic_string<
|
||||
char, std::char_traits<char>,
|
||||
Alloc>;
|
||||
|
||||
using result_type = string_type&;
|
||||
|
||||
explicit
|
||||
append_to_t(
|
||||
string_type& s) noexcept
|
||||
: s_(s)
|
||||
{
|
||||
}
|
||||
|
||||
char*
|
||||
prepare(std::size_t n) override
|
||||
{
|
||||
std::size_t n0 = s_.size();
|
||||
if(n > s_.max_size() - n0)
|
||||
urls::detail::throw_length_error();
|
||||
s_.resize(n0 + n);
|
||||
return &s_[n0];
|
||||
}
|
||||
|
||||
result_type
|
||||
result() noexcept
|
||||
{
|
||||
return s_;
|
||||
}
|
||||
|
||||
private:
|
||||
string_type& s_;
|
||||
};
|
||||
|
||||
template<
|
||||
class Alloc =
|
||||
std::allocator<char>>
|
||||
append_to_t<Alloc>
|
||||
append_to(
|
||||
std::basic_string<
|
||||
char,
|
||||
std::char_traits<char>,
|
||||
Alloc>& s)
|
||||
{
|
||||
return append_to_t<Alloc>(s);
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** A token for assigning to a plain string
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<
|
||||
class Allocator =
|
||||
std::allocator<char>>
|
||||
__implementation_defined__
|
||||
assign_to(
|
||||
std::basic_string<
|
||||
char,
|
||||
std::char_traits<char>,
|
||||
Allocator>& s);
|
||||
#else
|
||||
template<class Alloc>
|
||||
struct assign_to_t
|
||||
: arg
|
||||
{
|
||||
using string_type = std::basic_string<
|
||||
char, std::char_traits<char>,
|
||||
Alloc>;
|
||||
|
||||
using result_type = string_type&;
|
||||
|
||||
explicit
|
||||
assign_to_t(
|
||||
string_type& s) noexcept
|
||||
: s_(s)
|
||||
{
|
||||
}
|
||||
|
||||
char*
|
||||
prepare(std::size_t n) override
|
||||
{
|
||||
s_.resize(n);
|
||||
return &s_[0];
|
||||
}
|
||||
|
||||
result_type
|
||||
result() noexcept
|
||||
{
|
||||
return s_;
|
||||
}
|
||||
|
||||
private:
|
||||
string_type& s_;
|
||||
};
|
||||
|
||||
template<
|
||||
class Alloc =
|
||||
std::allocator<char>>
|
||||
assign_to_t<Alloc>
|
||||
assign_to(
|
||||
std::basic_string<
|
||||
char,
|
||||
std::char_traits<char>,
|
||||
Alloc>& s)
|
||||
{
|
||||
return assign_to_t<Alloc>(s);
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** A token for producing a durable core::string_view from a temporary string
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<
|
||||
class Allocator =
|
||||
std::allocator<char>>
|
||||
__implementation_defined__
|
||||
preserve_size(
|
||||
std::basic_string<
|
||||
char,
|
||||
std::char_traits<char>,
|
||||
Allocator>& s);
|
||||
#else
|
||||
template<class Alloc>
|
||||
struct preserve_size_t
|
||||
: arg
|
||||
{
|
||||
using result_type = core::string_view;
|
||||
|
||||
using string_type = std::basic_string<
|
||||
char, std::char_traits<char>,
|
||||
Alloc>;
|
||||
|
||||
explicit
|
||||
preserve_size_t(
|
||||
string_type& s) noexcept
|
||||
: s_(s)
|
||||
{
|
||||
}
|
||||
|
||||
char*
|
||||
prepare(std::size_t n) override
|
||||
{
|
||||
n_ = n;
|
||||
// preserve size() to
|
||||
// avoid value-init
|
||||
if(s_.size() < n)
|
||||
s_.resize(n);
|
||||
return &s_[0];
|
||||
}
|
||||
|
||||
result_type
|
||||
result() noexcept
|
||||
{
|
||||
return core::string_view(
|
||||
s_.data(), n_);
|
||||
}
|
||||
|
||||
private:
|
||||
string_type& s_;
|
||||
std::size_t n_ = 0;
|
||||
};
|
||||
|
||||
template<
|
||||
class Alloc =
|
||||
std::allocator<char>>
|
||||
preserve_size_t<Alloc>
|
||||
preserve_size(
|
||||
std::basic_string<
|
||||
char,
|
||||
std::char_traits<char>,
|
||||
Alloc>& s)
|
||||
{
|
||||
return preserve_size_t<Alloc>(s);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // string_token
|
||||
|
||||
namespace grammar {
|
||||
namespace string_token = ::boost::urls::string_token;
|
||||
} // grammar
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+877
@@ -0,0 +1,877 @@
|
||||
//
|
||||
// Copyright (c) 2022 Vinnie Falco (vinnie.falco@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_GRAMMAR_STRING_VIEW_BASE_HPP
|
||||
#define BOOST_URL_GRAMMAR_STRING_VIEW_BASE_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/detail/string_view.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** Common functionality for string views
|
||||
|
||||
This base class is used to provide common
|
||||
member functions for reference types that
|
||||
behave like string views. This cannot be
|
||||
instantiated directly; Instead, derive
|
||||
from the type and provide constructors
|
||||
which offer any desired preconditions
|
||||
and invariants.
|
||||
*/
|
||||
class string_view_base
|
||||
{
|
||||
protected:
|
||||
/** The referenced character buffer
|
||||
*/
|
||||
core::string_view s_;
|
||||
|
||||
/** Constructor
|
||||
*/
|
||||
constexpr
|
||||
string_view_base(
|
||||
core::string_view s) noexcept
|
||||
: s_(s)
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor
|
||||
*/
|
||||
constexpr
|
||||
string_view_base(
|
||||
char const* data,
|
||||
std::size_t size) noexcept
|
||||
: s_(data, size)
|
||||
{
|
||||
}
|
||||
|
||||
/** Swap
|
||||
*/
|
||||
// VFALCO No idea why this fails in msvc
|
||||
/*BOOST_CXX14_CONSTEXPR*/ void swap(
|
||||
string_view_base& s ) noexcept
|
||||
{
|
||||
std::swap(s_, s.s_);
|
||||
}
|
||||
|
||||
/** Constructor
|
||||
*/
|
||||
string_view_base() = default;
|
||||
|
||||
/** Constructor
|
||||
*/
|
||||
string_view_base(
|
||||
string_view_base const&) = default;
|
||||
|
||||
/** Assignment
|
||||
*/
|
||||
string_view_base& operator=(
|
||||
string_view_base const&) = default;
|
||||
|
||||
public:
|
||||
/// The character traits
|
||||
typedef std::char_traits<char> traits_type;
|
||||
/// The value type
|
||||
typedef char value_type;
|
||||
/// The pointer type
|
||||
typedef char* pointer;
|
||||
/// The const pointer type
|
||||
typedef char const* const_pointer;
|
||||
/// The reference type
|
||||
typedef char& reference;
|
||||
/// The const reference type
|
||||
typedef char const& const_reference;
|
||||
/// The const iterator type
|
||||
typedef char const* const_iterator;
|
||||
/// The iterator type
|
||||
typedef const_iterator iterator;
|
||||
/// The const reverse iterator type
|
||||
typedef std::reverse_iterator<
|
||||
const_iterator> const_reverse_iterator;
|
||||
/// The reverse iterator type
|
||||
typedef const_reverse_iterator reverse_iterator;
|
||||
/// The size type
|
||||
typedef std::size_t size_type;
|
||||
/// The difference type
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
/// A constant used to represent "no position"
|
||||
static constexpr std::size_t npos = core::string_view::npos;
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
/** Conversion
|
||||
*/
|
||||
operator
|
||||
core::string_view() const noexcept
|
||||
{
|
||||
return s_;
|
||||
}
|
||||
|
||||
/** Conversion
|
||||
*/
|
||||
#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
|
||||
operator
|
||||
std::string_view() const noexcept
|
||||
{
|
||||
return std::string_view(s_);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Conversion
|
||||
|
||||
Conversion to std::string is explicit
|
||||
because assigning to string using an
|
||||
implicit constructor does not preserve
|
||||
capacity.
|
||||
*/
|
||||
explicit
|
||||
operator
|
||||
std::string() const noexcept
|
||||
{
|
||||
return std::string(s_);
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
// iterator support
|
||||
|
||||
/** Return an iterator to the beginning
|
||||
|
||||
See `core::string_view::begin`
|
||||
*/
|
||||
BOOST_CONSTEXPR const_iterator begin() const noexcept
|
||||
{
|
||||
return s_.begin();
|
||||
}
|
||||
|
||||
/** Return an iterator to the end
|
||||
|
||||
See `core::string_view::end`
|
||||
*/
|
||||
BOOST_CONSTEXPR const_iterator end() const noexcept
|
||||
{
|
||||
return s_.end();
|
||||
}
|
||||
|
||||
/** Return an iterator to the beginning
|
||||
|
||||
See `core::string_view::cbegin`
|
||||
*/
|
||||
BOOST_CONSTEXPR const_iterator cbegin() const noexcept
|
||||
{
|
||||
return s_.cbegin();
|
||||
}
|
||||
|
||||
/** Return an iterator to the end
|
||||
|
||||
See `core::string_view::cend`
|
||||
*/
|
||||
BOOST_CONSTEXPR const_iterator cend() const noexcept
|
||||
{
|
||||
return s_.cend();
|
||||
}
|
||||
|
||||
/** Return a reverse iterator to the end
|
||||
|
||||
See `core::string_view::rbegin`
|
||||
*/
|
||||
#ifdef __cpp_lib_array_constexpr
|
||||
constexpr
|
||||
#endif
|
||||
const_reverse_iterator rbegin() const noexcept
|
||||
{
|
||||
return s_.rbegin();
|
||||
}
|
||||
|
||||
/** Return a reverse iterator to the beginning
|
||||
|
||||
See `core::string_view::rend`
|
||||
*/
|
||||
#ifdef __cpp_lib_array_constexpr
|
||||
constexpr
|
||||
#endif
|
||||
const_reverse_iterator rend() const noexcept
|
||||
{
|
||||
return s_.rend();
|
||||
}
|
||||
|
||||
/** Return a reverse iterator to the end
|
||||
|
||||
See `core::string_view::crbegin`
|
||||
*/
|
||||
#ifdef __cpp_lib_array_constexpr
|
||||
constexpr
|
||||
#endif
|
||||
const_reverse_iterator crbegin() const noexcept
|
||||
{
|
||||
return s_.crbegin();
|
||||
}
|
||||
|
||||
/** Return a reverse iterator to the beginning
|
||||
|
||||
See `core::string_view::crend`
|
||||
*/
|
||||
#ifdef __cpp_lib_array_constexpr
|
||||
constexpr
|
||||
#endif
|
||||
const_reverse_iterator crend() const noexcept
|
||||
{
|
||||
return s_.crend();
|
||||
}
|
||||
|
||||
// capacity
|
||||
|
||||
/** Return the size
|
||||
|
||||
See `core::string_view::size`
|
||||
*/
|
||||
BOOST_CONSTEXPR size_type size() const noexcept
|
||||
{
|
||||
return s_.size();
|
||||
}
|
||||
|
||||
/** Return the size
|
||||
|
||||
See `core::string_view::length`
|
||||
*/
|
||||
BOOST_CONSTEXPR size_type length() const noexcept
|
||||
{
|
||||
return s_.length();
|
||||
}
|
||||
|
||||
/** Return the maximum allowed size
|
||||
|
||||
See `core::string_view::max_size`
|
||||
*/
|
||||
BOOST_CONSTEXPR size_type max_size() const noexcept
|
||||
{
|
||||
return s_.max_size();
|
||||
}
|
||||
|
||||
/** Return true if the string is empty
|
||||
|
||||
See `core::string_view::size`
|
||||
*/
|
||||
BOOST_CONSTEXPR bool empty() const noexcept
|
||||
{
|
||||
return s_.empty();
|
||||
}
|
||||
|
||||
// element access
|
||||
|
||||
/** Access a character
|
||||
|
||||
See `core::string_view::operator[]`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR const_reference
|
||||
operator[]( size_type pos ) const noexcept
|
||||
{
|
||||
return s_[pos];
|
||||
}
|
||||
|
||||
/** Access a character
|
||||
|
||||
See `core::string_view::at`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR const_reference
|
||||
at( size_type pos ) const
|
||||
{
|
||||
return s_.at(pos);
|
||||
}
|
||||
|
||||
/** Return the first character
|
||||
|
||||
See `core::string_view::front`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR const_reference
|
||||
front() const noexcept
|
||||
{
|
||||
return s_.front();
|
||||
}
|
||||
|
||||
/** Return the last character
|
||||
|
||||
See `core::string_view::back`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR const_reference
|
||||
back() const noexcept
|
||||
{
|
||||
return s_.back();
|
||||
}
|
||||
|
||||
/** Return a pointer to the character buffer
|
||||
|
||||
See `core::string_view::data`
|
||||
*/
|
||||
BOOST_CONSTEXPR const_pointer
|
||||
data() const noexcept
|
||||
{
|
||||
return s_.data();
|
||||
}
|
||||
|
||||
// string operations
|
||||
|
||||
/** Copy the characters to another buffer
|
||||
|
||||
See `core::string_view::copy`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR size_type copy(
|
||||
char* s, size_type n, size_type pos = 0 ) const
|
||||
{
|
||||
return s_.copy(s, n, pos);
|
||||
}
|
||||
|
||||
/** Return a view to part of the string
|
||||
|
||||
See `core::string_view::substr`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR core::string_view substr(
|
||||
size_type pos = 0, size_type n = core::string_view::npos ) const
|
||||
{
|
||||
return s_.substr(pos, n);
|
||||
}
|
||||
|
||||
// comparison
|
||||
|
||||
/** Return the result of comparing to another string
|
||||
|
||||
See `core::string_view::compare`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR int
|
||||
compare( core::string_view str ) const noexcept
|
||||
{
|
||||
return s_.compare(str);
|
||||
}
|
||||
|
||||
/** Return the result of comparing to another string
|
||||
|
||||
See `core::string_view::compare`
|
||||
*/
|
||||
BOOST_CONSTEXPR int compare(
|
||||
size_type pos1, size_type n1, core::string_view str ) const
|
||||
{
|
||||
return s_.compare(pos1, n1, str);
|
||||
}
|
||||
|
||||
/** Return the result of comparing to another string
|
||||
|
||||
See `core::string_view::compare`
|
||||
*/
|
||||
BOOST_CONSTEXPR int compare(
|
||||
size_type pos1, size_type n1, core::string_view str,
|
||||
size_type pos2, size_type n2 ) const
|
||||
{
|
||||
return s_.compare(pos1, n1, str, pos2, n2);
|
||||
}
|
||||
|
||||
/** Return the result of comparing to another string
|
||||
|
||||
See `core::string_view::compare`
|
||||
*/
|
||||
BOOST_CONSTEXPR int compare(
|
||||
char const* s ) const noexcept
|
||||
{
|
||||
return s_.compare(s);
|
||||
}
|
||||
|
||||
/** Return the result of comparing to another string
|
||||
|
||||
See `core::string_view::compare`
|
||||
*/
|
||||
BOOST_CONSTEXPR int compare(
|
||||
size_type pos1, size_type n1, char const* s ) const
|
||||
{
|
||||
return s_.compare(pos1, n1, s);
|
||||
}
|
||||
|
||||
/** Return the result of comparing to another string
|
||||
|
||||
See `core::string_view::compare`
|
||||
*/
|
||||
BOOST_CONSTEXPR int compare(
|
||||
size_type pos1, size_type n1,
|
||||
char const* s, size_type n2 ) const
|
||||
{
|
||||
return s_.compare(pos1, n1, s, n2);
|
||||
}
|
||||
|
||||
// starts_with
|
||||
|
||||
/** Return true if a matching prefix exists
|
||||
|
||||
See `core::string_view::starts_with`
|
||||
*/
|
||||
BOOST_CONSTEXPR bool starts_with(
|
||||
core::string_view x ) const noexcept
|
||||
{
|
||||
return s_.starts_with(x);
|
||||
}
|
||||
|
||||
/** Return true if a matching prefix exists
|
||||
|
||||
See `core::string_view::starts_with`
|
||||
*/
|
||||
BOOST_CONSTEXPR bool starts_with(
|
||||
char x ) const noexcept
|
||||
{
|
||||
return s_.starts_with(x);
|
||||
}
|
||||
|
||||
/** Return true if a matching prefix exists
|
||||
|
||||
See `core::string_view::starts_with`
|
||||
*/
|
||||
BOOST_CONSTEXPR bool starts_with(
|
||||
char const* x ) const noexcept
|
||||
{
|
||||
return s_.starts_with(x);
|
||||
}
|
||||
|
||||
// ends_with
|
||||
|
||||
/** Return true if a matching suffix exists
|
||||
|
||||
See `core::string_view::ends_with`
|
||||
*/
|
||||
BOOST_CONSTEXPR bool ends_with(
|
||||
core::string_view x ) const noexcept
|
||||
{
|
||||
return s_.ends_with(x);
|
||||
}
|
||||
|
||||
/** Return true if a matching suffix exists
|
||||
|
||||
See `core::string_view::ends_with`
|
||||
*/
|
||||
BOOST_CONSTEXPR bool ends_with(
|
||||
char x ) const noexcept
|
||||
{
|
||||
return s_.ends_with(x);
|
||||
}
|
||||
|
||||
/** Return true if a matching suffix exists
|
||||
|
||||
See `core::string_view::ends_with`
|
||||
*/
|
||||
BOOST_CONSTEXPR bool ends_with(
|
||||
char const* x ) const noexcept
|
||||
{
|
||||
return s_.ends_with(x);
|
||||
}
|
||||
|
||||
// find
|
||||
|
||||
/** Return the position of matching characters
|
||||
|
||||
See `core::string_view::find`
|
||||
*/
|
||||
BOOST_CONSTEXPR size_type find(
|
||||
core::string_view str, size_type pos = 0 ) const noexcept
|
||||
{
|
||||
return s_.find(str, pos);
|
||||
}
|
||||
|
||||
/** Return the position of matching characters
|
||||
|
||||
See `core::string_view::find`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR size_type find(
|
||||
char c, size_type pos = 0 ) const noexcept
|
||||
{
|
||||
return s_.find(c, pos);
|
||||
}
|
||||
|
||||
/** Return the position of matching characters
|
||||
|
||||
See `core::string_view::find`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR size_type find(
|
||||
char const* s, size_type pos, size_type n ) const noexcept
|
||||
{
|
||||
return s_.find(s, pos, n);
|
||||
}
|
||||
|
||||
/** Return the position of matching characters
|
||||
|
||||
See `core::string_view::find`
|
||||
*/
|
||||
BOOST_CONSTEXPR size_type find(
|
||||
char const* s, size_type pos = 0 ) const noexcept
|
||||
{
|
||||
return s_.find(s, pos);
|
||||
}
|
||||
|
||||
// rfind
|
||||
|
||||
/** Return the position of matching characters
|
||||
|
||||
See `core::string_view::rfind`
|
||||
*/
|
||||
BOOST_CONSTEXPR size_type rfind(
|
||||
core::string_view str, size_type pos = core::string_view::npos ) const noexcept
|
||||
{
|
||||
return s_.rfind(str, pos);
|
||||
}
|
||||
|
||||
/** Return the position of matching characters
|
||||
|
||||
See `core::string_view::rfind`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(
|
||||
char c, size_type pos = core::string_view::npos ) const noexcept
|
||||
{
|
||||
return s_.rfind(c, pos);
|
||||
}
|
||||
|
||||
/** Return the position of matching characters
|
||||
|
||||
See `core::string_view::rfind`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(
|
||||
char const* s, size_type pos, size_type n ) const noexcept
|
||||
{
|
||||
return s_.rfind(s, pos, n);
|
||||
}
|
||||
|
||||
/** Return the position of matching characters
|
||||
|
||||
See `core::string_view::rfind`
|
||||
*/
|
||||
BOOST_CONSTEXPR size_type rfind(
|
||||
char const* s, size_type pos = core::string_view::npos ) const noexcept
|
||||
{
|
||||
return s_.rfind(s, pos);
|
||||
}
|
||||
|
||||
// find_first_of
|
||||
|
||||
/** Return the position of the first match
|
||||
|
||||
See `core::string_view::find_first_of`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(
|
||||
core::string_view str, size_type pos = 0 ) const noexcept
|
||||
{
|
||||
return s_.find_first_of(str, pos);
|
||||
}
|
||||
|
||||
/** Return the position of the first match
|
||||
|
||||
See `core::string_view::find_first_of`
|
||||
*/
|
||||
BOOST_CONSTEXPR size_type find_first_of(
|
||||
char c, size_type pos = 0 ) const noexcept
|
||||
{
|
||||
return s_.find_first_of(c, pos);
|
||||
}
|
||||
|
||||
/** Return the position of the first match
|
||||
|
||||
See `core::string_view::find_first_of`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(
|
||||
char const* s, size_type pos, size_type n ) const noexcept
|
||||
{
|
||||
return s_.find_first_of(s, pos, n);
|
||||
}
|
||||
|
||||
/** Return the position of the first match
|
||||
|
||||
See `core::string_view::find_first_of`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(
|
||||
char const* s, size_type pos = 0 ) const noexcept
|
||||
{
|
||||
return s_.find_first_of(s, pos);
|
||||
}
|
||||
|
||||
// find_last_of
|
||||
|
||||
/** Return the position of the last match
|
||||
|
||||
See `core::string_view::find_last_of`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(
|
||||
core::string_view str, size_type pos = core::string_view::npos ) const noexcept
|
||||
{
|
||||
return s_.find_last_of(str, pos);
|
||||
}
|
||||
|
||||
/** Return the position of the last match
|
||||
|
||||
See `core::string_view::find_last_of`
|
||||
*/
|
||||
BOOST_CONSTEXPR size_type find_last_of(
|
||||
char c, size_type pos = core::string_view::npos ) const noexcept
|
||||
{
|
||||
return s_.find_last_of(c, pos);
|
||||
}
|
||||
|
||||
/** Return the position of the last match
|
||||
|
||||
See `core::string_view::find_last_of`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(
|
||||
char const* s, size_type pos, size_type n ) const noexcept
|
||||
{
|
||||
return s_.find_last_of(s, pos, n);
|
||||
}
|
||||
|
||||
/** Return the position of the last match
|
||||
|
||||
See `core::string_view::find_last_of`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(
|
||||
char const* s, size_type pos = core::string_view::npos ) const noexcept
|
||||
{
|
||||
return s_.find_last_of(s, pos);
|
||||
}
|
||||
|
||||
// find_first_not_of
|
||||
|
||||
/** Return the position of the first non-match
|
||||
|
||||
See `core::string_view::find_first_not_of`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
|
||||
core::string_view str, size_type pos = 0 ) const noexcept
|
||||
{
|
||||
return s_.find_first_not_of(str, pos);
|
||||
}
|
||||
|
||||
/** Return the position of the first non-match
|
||||
|
||||
See `core::string_view::find_first_not_of`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
|
||||
char c, size_type pos = 0 ) const noexcept
|
||||
{
|
||||
return s_.find_first_not_of(c, pos);
|
||||
}
|
||||
|
||||
/** Return the position of the first non-match
|
||||
|
||||
See `core::string_view::find_first_not_of`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
|
||||
char const* s, size_type pos, size_type n ) const noexcept
|
||||
{
|
||||
return s_.find_first_not_of(s, pos, n);
|
||||
}
|
||||
|
||||
/** Return the position of the first non-match
|
||||
|
||||
See `core::string_view::find_first_not_of`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
|
||||
char const* s, size_type pos = 0 ) const noexcept
|
||||
{
|
||||
return s_.find_first_not_of(s, pos);
|
||||
}
|
||||
|
||||
// find_last_not_of
|
||||
|
||||
/** Return the position of the last non-match
|
||||
|
||||
See `core::string_view::find_last_not_of`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
|
||||
core::string_view str, size_type pos = core::string_view::npos ) const noexcept
|
||||
{
|
||||
return s_.find_last_not_of(str, pos);
|
||||
}
|
||||
|
||||
/** Return the position of the last non-match
|
||||
|
||||
See `core::string_view::find_last_not_of`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
|
||||
char c, size_type pos = core::string_view::npos ) const noexcept
|
||||
{
|
||||
return s_.find_last_not_of(c, pos);
|
||||
}
|
||||
|
||||
/** Return the position of the last non-match
|
||||
|
||||
See `core::string_view::find_last_not_of`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
|
||||
char const* s, size_type pos, size_type n ) const noexcept
|
||||
{
|
||||
return s_.find_last_not_of(s, pos, n);
|
||||
}
|
||||
|
||||
/** Return the position of the last non-match
|
||||
|
||||
See `core::string_view::find_last_not_of`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
|
||||
char const* s, size_type pos = core::string_view::npos ) const noexcept
|
||||
{
|
||||
return s_.find_last_not_of(s, pos);
|
||||
}
|
||||
|
||||
// contains
|
||||
|
||||
/** Return true if matching characters are found
|
||||
|
||||
See `core::string_view::contains`
|
||||
*/
|
||||
BOOST_CONSTEXPR bool contains( core::string_view sv ) const noexcept
|
||||
{
|
||||
return s_.contains(sv);
|
||||
}
|
||||
|
||||
/** Return true if matching characters are found
|
||||
|
||||
See `core::string_view::contains`
|
||||
*/
|
||||
BOOST_CXX14_CONSTEXPR bool contains( char c ) const noexcept
|
||||
{
|
||||
return s_.contains(c);
|
||||
}
|
||||
|
||||
/** Return true if matching characters are found
|
||||
|
||||
See `core::string_view::contains`
|
||||
*/
|
||||
BOOST_CONSTEXPR bool contains( char const* s ) const noexcept
|
||||
{
|
||||
return s_.contains(s);
|
||||
}
|
||||
|
||||
// relational operators
|
||||
#ifndef BOOST_URL_DOCS
|
||||
private:
|
||||
template<class S0, class S1>
|
||||
using is_match = std::integral_constant<bool,
|
||||
std::is_convertible<S0, core::string_view>::value &&
|
||||
std::is_convertible<S1, core::string_view>::value && (
|
||||
(std::is_base_of<string_view_base,
|
||||
typename std::decay<S0>::type>::value &&
|
||||
std::is_convertible<S0 const volatile*,
|
||||
string_view_base const volatile*>::value) ||
|
||||
(std::is_base_of<string_view_base,
|
||||
typename std::decay<S1>::type>::value &&
|
||||
std::is_convertible<S1 const volatile*,
|
||||
string_view_base const volatile*>::value))>;
|
||||
public:
|
||||
|
||||
template<class S0, class S1>
|
||||
BOOST_CXX14_CONSTEXPR friend auto operator==(
|
||||
S0 const& s0, S1 const& s1) noexcept ->
|
||||
typename std::enable_if<
|
||||
is_match<S0, S1>::value, bool>::type
|
||||
{
|
||||
return urls::detail::to_sv(s0) == urls::detail::to_sv(s1);
|
||||
}
|
||||
|
||||
template<class S0, class S1>
|
||||
BOOST_CXX14_CONSTEXPR friend auto operator!=(
|
||||
S0 const& s0, S1 const& s1) noexcept ->
|
||||
typename std::enable_if<
|
||||
is_match<S0, S1>::value, bool>::type
|
||||
{
|
||||
return urls::detail::to_sv(s0) != urls::detail::to_sv(s1);
|
||||
}
|
||||
|
||||
template<class S0, class S1>
|
||||
BOOST_CXX14_CONSTEXPR friend auto operator<(
|
||||
S0 const& s0, S1 const& s1) noexcept ->
|
||||
typename std::enable_if<
|
||||
is_match<S0, S1>::value, bool>::type
|
||||
{
|
||||
return urls::detail::to_sv(s0) < urls::detail::to_sv(s1);
|
||||
}
|
||||
|
||||
template<class S0, class S1>
|
||||
BOOST_CXX14_CONSTEXPR friend auto operator<=(
|
||||
S0 const& s0, S1 const& s1) noexcept ->
|
||||
typename std::enable_if<
|
||||
is_match<S0, S1>::value, bool>::type
|
||||
{
|
||||
return urls::detail::to_sv(s0) <= urls::detail::to_sv(s1);
|
||||
}
|
||||
|
||||
template<class S0, class S1>
|
||||
BOOST_CXX14_CONSTEXPR friend auto operator>(
|
||||
S0 const& s0, S1 const& s1) noexcept ->
|
||||
typename std::enable_if<
|
||||
is_match<S0, S1>::value, bool>::type
|
||||
{
|
||||
return urls::detail::to_sv(s0) > urls::detail::to_sv(s1);
|
||||
}
|
||||
|
||||
template<class S0, class S1>
|
||||
BOOST_CXX14_CONSTEXPR friend auto operator>=(
|
||||
S0 const& s0, S1 const& s1) noexcept ->
|
||||
typename std::enable_if<
|
||||
is_match<S0, S1>::value, bool>::type
|
||||
{
|
||||
return urls::detail::to_sv(s0) >= urls::detail::to_sv(s1);
|
||||
}
|
||||
#endif
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
/** Return the hash of this value
|
||||
*/
|
||||
friend
|
||||
std::size_t
|
||||
hash_value(
|
||||
string_view_base const& s) noexcept
|
||||
{
|
||||
return hash_value(s.s_);
|
||||
}
|
||||
|
||||
BOOST_URL_DECL
|
||||
friend
|
||||
std::ostream&
|
||||
operator<<(
|
||||
std::ostream& os,
|
||||
string_view_base const& s);
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Format a string to an output stream
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
std::ostream&
|
||||
operator<<(
|
||||
std::ostream& os,
|
||||
string_view_base const& s);
|
||||
|
||||
} // grammar
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
namespace detail {
|
||||
template <>
|
||||
inline
|
||||
core::string_view
|
||||
to_sv(grammar::string_view_base const& s) noexcept
|
||||
{
|
||||
return s.operator core::string_view();
|
||||
}
|
||||
} // detail
|
||||
#endif
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/http_proto
|
||||
//
|
||||
|
||||
#ifndef BOOST_URL_GRAMMAR_TOKEN_RULE_HPP
|
||||
#define BOOST_URL_GRAMMAR_TOKEN_RULE_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/grammar/charset.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** Match a non-empty string of characters from a set
|
||||
|
||||
If there is no more input, the error code
|
||||
@ref error::need_more is returned.
|
||||
|
||||
@par Value Type
|
||||
@code
|
||||
using value_type = core::string_view;
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
Rules are used with the function @ref parse.
|
||||
@code
|
||||
system::result< core::string_view > rv = parse( "abcdef", token_rule( alpha_chars ) );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
token = 1*( ch )
|
||||
@endcode
|
||||
|
||||
@param cs The character set to use
|
||||
|
||||
@see
|
||||
@ref alpha_chars,
|
||||
@ref parse.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<class CharSet>
|
||||
constexpr
|
||||
__implementation_defined__
|
||||
token_rule(
|
||||
CharSet cs) noexcept;
|
||||
#else
|
||||
template<class CharSet>
|
||||
struct token_rule_t
|
||||
{
|
||||
using value_type = core::string_view;
|
||||
|
||||
static_assert(
|
||||
is_charset<CharSet>::value,
|
||||
"CharSet requirements not met");
|
||||
|
||||
auto
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end
|
||||
) const noexcept ->
|
||||
system::result<value_type>;
|
||||
|
||||
private:
|
||||
template<class CharSet_>
|
||||
friend
|
||||
constexpr
|
||||
auto
|
||||
token_rule(
|
||||
CharSet_ const&) noexcept ->
|
||||
token_rule_t<CharSet_>;
|
||||
|
||||
constexpr
|
||||
token_rule_t(
|
||||
CharSet const& cs) noexcept
|
||||
: cs_(cs)
|
||||
{
|
||||
}
|
||||
|
||||
CharSet const cs_;
|
||||
};
|
||||
|
||||
template<class CharSet>
|
||||
constexpr
|
||||
auto
|
||||
token_rule(
|
||||
CharSet const& cs) noexcept ->
|
||||
token_rule_t<CharSet>
|
||||
{
|
||||
return {cs};
|
||||
}
|
||||
#endif
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#include <boost/url/grammar/impl/token_rule.hpp>
|
||||
|
||||
#endif
|
||||
+248
@@ -0,0 +1,248 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_TUPLE_RULE_HPP
|
||||
#define BOOST_URL_GRAMMAR_TUPLE_RULE_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <boost/url/grammar/error.hpp>
|
||||
#include <boost/url/grammar/detail/tuple.hpp>
|
||||
#include <boost/mp11/algorithm.hpp>
|
||||
#include <boost/core/empty_value.hpp>
|
||||
#include <tuple>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** Match a series of rules in order
|
||||
|
||||
This matches a series of rules in the
|
||||
order specified. Upon success the input
|
||||
is adjusted to point to the first
|
||||
unconsumed character. There is no
|
||||
implicit specification of linear white
|
||||
space between each rule.
|
||||
|
||||
@par Value Type
|
||||
@code
|
||||
using value_type = __see_below__;
|
||||
@endcode
|
||||
|
||||
The sequence rule usually returns a
|
||||
`std::tuple` containing the the `value_type`
|
||||
of each corresponding rule in the sequence,
|
||||
except that `void` values are removed.
|
||||
However, if there is exactly one non-void
|
||||
value type `T`, then the sequence rule
|
||||
returns `system::result<T>` instead of
|
||||
`system::result<tuple<...>>`.
|
||||
|
||||
@par Example
|
||||
Rules are used with the function @ref parse.
|
||||
@code
|
||||
system::result< std::tuple< unsigned char, unsigned char, unsigned char, unsigned char > > rv =
|
||||
parse( "192.168.0.1",
|
||||
tuple_rule(
|
||||
dec_octet_rule,
|
||||
squelch( delim_rule('.') ),
|
||||
dec_octet_rule,
|
||||
squelch( delim_rule('.') ),
|
||||
dec_octet_rule,
|
||||
squelch( delim_rule('.') ),
|
||||
dec_octet_rule ) );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
sequence = rule1 rule2 rule3...
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc5234#section-3.1"
|
||||
>3.1. Concatenation (rfc5234)</a>
|
||||
|
||||
@param rn A list of one or more rules to match
|
||||
|
||||
@see
|
||||
@ref dec_octet_rule,
|
||||
@ref delim_rule,
|
||||
@ref parse,
|
||||
@ref squelch.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<class... Rules>
|
||||
constexpr
|
||||
__implementation_defined__
|
||||
tuple_rule( Rules... rn ) noexcept;
|
||||
#else
|
||||
template<
|
||||
class R0,
|
||||
class... Rn>
|
||||
class tuple_rule_t
|
||||
: empty_value<
|
||||
detail::tuple<R0, Rn...>>
|
||||
{
|
||||
using T = mp11::mp_remove<
|
||||
std::tuple<
|
||||
typename R0::value_type,
|
||||
typename Rn::value_type...>,
|
||||
void>;
|
||||
static constexpr bool IsList =
|
||||
mp11::mp_size<T>::value != 1;
|
||||
|
||||
public:
|
||||
using value_type =
|
||||
mp11::mp_eval_if_c<IsList,
|
||||
T, mp11::mp_first, T>;
|
||||
|
||||
template<
|
||||
class R0_,
|
||||
class... Rn_>
|
||||
friend
|
||||
constexpr
|
||||
auto
|
||||
tuple_rule(
|
||||
R0_ const& r0,
|
||||
Rn_ const&... rn) noexcept ->
|
||||
tuple_rule_t<R0_, Rn_...>;
|
||||
|
||||
system::result<value_type>
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const;
|
||||
|
||||
private:
|
||||
constexpr
|
||||
tuple_rule_t(
|
||||
R0 const& r0,
|
||||
Rn const&... rn) noexcept
|
||||
: empty_value<
|
||||
detail::tuple<R0, Rn...>>(
|
||||
empty_init,
|
||||
r0, rn...)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<
|
||||
class R0,
|
||||
class... Rn>
|
||||
constexpr
|
||||
auto
|
||||
tuple_rule(
|
||||
R0 const& r0,
|
||||
Rn const&... rn) noexcept ->
|
||||
tuple_rule_t<
|
||||
R0, Rn...>
|
||||
{
|
||||
return { r0, rn... };
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
namespace detail {
|
||||
|
||||
template<class Rule>
|
||||
struct squelch_rule_t
|
||||
: empty_value<Rule>
|
||||
{
|
||||
using value_type = void;
|
||||
|
||||
constexpr
|
||||
squelch_rule_t(
|
||||
Rule const& r) noexcept
|
||||
: empty_value<Rule>(
|
||||
empty_init, r)
|
||||
{
|
||||
}
|
||||
|
||||
system::result<value_type>
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const
|
||||
{
|
||||
auto rv = this->get().parse(it, end);
|
||||
if(rv.error())
|
||||
return rv.error();
|
||||
return {}; // void
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
#endif
|
||||
|
||||
/** Squelch the value of a rule
|
||||
|
||||
This function returns a new rule which
|
||||
matches the specified rule, and converts
|
||||
its value type to `void`. This is useful
|
||||
for matching delimiters in a grammar,
|
||||
where the value for the delimiter is not
|
||||
needed.
|
||||
|
||||
@par Value Type
|
||||
@code
|
||||
using value_type = void;
|
||||
@endcode
|
||||
|
||||
@par Example 1
|
||||
With `squelch`:
|
||||
@code
|
||||
system::result< std::tuple< decode_view, core::string_view > > rv = parse(
|
||||
"www.example.com:443",
|
||||
tuple_rule(
|
||||
pct_encoded_rule(unreserved_chars + '-' + '.'),
|
||||
squelch( delim_rule( ':' ) ),
|
||||
token_rule( digit_chars ) ) );
|
||||
@endcode
|
||||
|
||||
@par Example 2
|
||||
Without `squelch`:
|
||||
@code
|
||||
system::result< std::tuple< decode_view, core::string_view, core::string_view > > rv = parse(
|
||||
"www.example.com:443",
|
||||
tuple_rule(
|
||||
pct_encoded_rule(unreserved_chars + '-' + '.'),
|
||||
delim_rule( ':' ),
|
||||
token_rule( digit_chars ) ) );
|
||||
@endcode
|
||||
|
||||
@param r The rule to squelch
|
||||
|
||||
@see
|
||||
@ref delim_rule,
|
||||
@ref digit_chars,
|
||||
@ref parse,
|
||||
@ref tuple_rule,
|
||||
@ref token_rule,
|
||||
@ref decode_view,
|
||||
@ref pct_encoded_rule,
|
||||
@ref unreserved_chars.
|
||||
*/
|
||||
template<class Rule>
|
||||
constexpr
|
||||
#ifdef BOOST_URL_DOCS
|
||||
__implementation_defined__
|
||||
#else
|
||||
detail::squelch_rule_t<Rule>
|
||||
#endif
|
||||
squelch( Rule const& r ) noexcept
|
||||
{
|
||||
return { r };
|
||||
}
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#include <boost/url/grammar/impl/tuple_rule.hpp>
|
||||
|
||||
#endif
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
//
|
||||
// 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_GRAMMAR_TYPE_TRAITS_HPP
|
||||
#define BOOST_URL_GRAMMAR_TYPE_TRAITS_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** Determine if T meets the requirements of Rule
|
||||
|
||||
This is an alias for `std::true_type` if
|
||||
`T` meets the requirements, otherwise it
|
||||
is an alias for `std::false_type`.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
struct U
|
||||
{
|
||||
struct value_type;
|
||||
|
||||
auto
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const ->
|
||||
system::result<value_type>
|
||||
};
|
||||
|
||||
static_assert( is_rule<U>::value, "Requirements not met" );
|
||||
@endcode
|
||||
|
||||
@see
|
||||
@ref parse.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<class T>
|
||||
using is_rule = __see_below__;
|
||||
#else
|
||||
template<class T, class = void>
|
||||
struct is_rule : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_rule<T, void_t<decltype(
|
||||
std::declval<system::result<typename T::value_type>&>() =
|
||||
std::declval<T const&>().parse(
|
||||
std::declval<char const*&>(),
|
||||
std::declval<char const*>())
|
||||
)>> : std::is_nothrow_copy_constructible<T>
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
// Copyright (c) 2022 Alan de Freitas (alandefreitas at gmail dot 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_GRAMMAR_UNSIGNED_RULE_HPP
|
||||
#define BOOST_URL_GRAMMAR_UNSIGNED_RULE_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <boost/url/grammar/charset.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** Match an unsigned decimal
|
||||
|
||||
Extra leading zeroes are disallowed.
|
||||
|
||||
@par Value Type
|
||||
@code
|
||||
using value_type = Unsigned;
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
Rules are used with the function @ref parse.
|
||||
@code
|
||||
system::result< unsigned short > rv = parse( "32767", unsigned_rule< unsigned short >{} );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
unsigned = "0" / ( ["1"..."9"] *DIGIT )
|
||||
@endcode
|
||||
|
||||
@tparam Unsigned The unsigned integer type used
|
||||
to store the result.
|
||||
|
||||
@see
|
||||
@ref grammar::parse.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<class Unsigned>
|
||||
struct unsigned_rule;
|
||||
#else
|
||||
template<class Unsigned>
|
||||
struct unsigned_rule
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
std::numeric_limits<
|
||||
Unsigned>::is_integer &&
|
||||
! std::numeric_limits<
|
||||
Unsigned>::is_signed);
|
||||
|
||||
using value_type = Unsigned;
|
||||
|
||||
auto
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end
|
||||
) const noexcept ->
|
||||
system::result<value_type>;
|
||||
};
|
||||
#endif
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#include <boost/url/grammar/impl/unsigned_rule.hpp>
|
||||
|
||||
#endif
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_VARIANT_RULE_HPP
|
||||
#define BOOST_URL_GRAMMAR_VARIANT_RULE_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <boost/url/variant.hpp>
|
||||
#include <boost/url/grammar/detail/tuple.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** Match one of a set of rules
|
||||
|
||||
Each specified rule is tried in sequence.
|
||||
When the first match occurs, the result
|
||||
is stored and returned in the variant. If
|
||||
no match occurs, an error is returned.
|
||||
|
||||
@par Value Type
|
||||
@code
|
||||
using value_type = variant< typename Rules::value_type... >;
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
Rules are used with the function @ref parse.
|
||||
@code
|
||||
// request-target = origin-form
|
||||
// / absolute-form
|
||||
// / authority-form
|
||||
// / asterisk-form
|
||||
|
||||
system::result< variant< url_view, url_view, authority_view, core::string_view > > rv = grammar::parse(
|
||||
"/index.html?width=full",
|
||||
variant_rule(
|
||||
origin_form_rule,
|
||||
absolute_uri_rule,
|
||||
authority_rule,
|
||||
delim_rule('*') ) );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
variant = rule1 / rule2 / rule3...
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc5234#section-3.2"
|
||||
>3.2. Alternatives (rfc5234)</a>
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc7230#section-5.3"
|
||||
>5.3. Request Target (rfc7230)</a>
|
||||
|
||||
@see
|
||||
@ref absolute_uri_rule,
|
||||
@ref authority_rule,
|
||||
@ref delim_rule,
|
||||
@ref parse,
|
||||
@ref origin_form_rule,
|
||||
@ref url_view.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<class... Rules>
|
||||
constexpr
|
||||
__implementation_defined__
|
||||
variant_rule( Rules... rn ) noexcept;
|
||||
#else
|
||||
template<
|
||||
class R0, class... Rn>
|
||||
class variant_rule_t
|
||||
{
|
||||
public:
|
||||
using value_type = variant<
|
||||
typename R0::value_type,
|
||||
typename Rn::value_type...>;
|
||||
|
||||
auto
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end) const ->
|
||||
system::result<value_type>;
|
||||
|
||||
template<
|
||||
class R0_,
|
||||
class... Rn_>
|
||||
friend
|
||||
constexpr
|
||||
auto
|
||||
variant_rule(
|
||||
R0_ const& r0,
|
||||
Rn_ const&... rn) noexcept ->
|
||||
variant_rule_t<R0_, Rn_...>;
|
||||
|
||||
private:
|
||||
constexpr
|
||||
variant_rule_t(
|
||||
R0 const& r0,
|
||||
Rn const&... rn) noexcept
|
||||
: rn_(r0, rn...)
|
||||
{
|
||||
}
|
||||
|
||||
detail::tuple<R0, Rn...> rn_;
|
||||
};
|
||||
|
||||
template<
|
||||
class R0,
|
||||
class... Rn>
|
||||
constexpr
|
||||
auto
|
||||
variant_rule(
|
||||
R0 const& r0,
|
||||
Rn const&... rn) noexcept ->
|
||||
variant_rule_t<R0, Rn...>;
|
||||
#endif
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#include <boost/url/grammar/impl/variant_rule.hpp>
|
||||
|
||||
#endif
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
//
|
||||
// Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_VCHARS_HPP
|
||||
#define BOOST_URL_GRAMMAR_VCHARS_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/grammar/detail/charset.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace grammar {
|
||||
|
||||
/** The set of visible characters
|
||||
|
||||
@par Example
|
||||
Character sets are used with rules and the
|
||||
functions @ref find_if and @ref find_if_not.
|
||||
@code
|
||||
system::result< core::string_view > rv = parse( "JohnDoe", token_rule( vchars ) );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
VCHAR = 0x21-0x7E
|
||||
; visible (printing) characters
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc5234#appendix-B.1"
|
||||
>B.1. Core Rules (rfc5234)</a>
|
||||
|
||||
@see
|
||||
@ref find_if,
|
||||
@ref find_if_not,
|
||||
@ref parse,
|
||||
@ref token_rule.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
constexpr __implementation_defined__ vchars;
|
||||
#else
|
||||
struct vchars_t
|
||||
{
|
||||
constexpr
|
||||
bool
|
||||
operator()(char c) const noexcept
|
||||
{
|
||||
return c >= 0x21 && c <= 0x7e;
|
||||
}
|
||||
|
||||
#ifdef BOOST_URL_USE_SSE2
|
||||
char const*
|
||||
find_if(
|
||||
char const* first,
|
||||
char const* last) const noexcept
|
||||
{
|
||||
return detail::find_if_pred(
|
||||
*this, first, last);
|
||||
}
|
||||
|
||||
char const*
|
||||
find_if_not(
|
||||
char const* first,
|
||||
char const* last) const noexcept
|
||||
{
|
||||
return detail::find_if_not_pred(
|
||||
*this, first, last);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
constexpr vchars_t vchars{};
|
||||
#endif
|
||||
|
||||
} // grammar
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_HOST_TYPE_HPP
|
||||
#define BOOST_URL_HOST_TYPE_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
/** Identifies the type of host in a URL.
|
||||
|
||||
Values of this type are returned by URL views
|
||||
and containers to indicate the type of host
|
||||
present in a URL.
|
||||
*/
|
||||
enum class host_type
|
||||
{
|
||||
// VFALCO 3 space indent or
|
||||
// else Doxygen malfunctions
|
||||
|
||||
/**
|
||||
* No host is specified.
|
||||
*/
|
||||
none,
|
||||
|
||||
/**
|
||||
* A host is specified by reg-name.
|
||||
*/
|
||||
name,
|
||||
|
||||
/**
|
||||
* A host is specified by @ref ipv4_address.
|
||||
*/
|
||||
ipv4,
|
||||
|
||||
/**
|
||||
* A host is specified by @ref ipv6_address.
|
||||
*/
|
||||
ipv6,
|
||||
|
||||
/**
|
||||
* A host is specified by IPvFuture.
|
||||
*/
|
||||
ipvfuture
|
||||
};
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_IGNORE_CASE_HPP
|
||||
#define BOOST_URL_IGNORE_CASE_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
struct ignore_case_t
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
/** Ignore case when comparing
|
||||
|
||||
This value may be optionally passed to
|
||||
functions accepting a parameter of type
|
||||
@ref ignore_case_param to indicate that
|
||||
comparisons should be case-insensitive.
|
||||
*/
|
||||
constexpr
|
||||
#ifdef BOOST_URL_DOCS
|
||||
__implementation_defined__
|
||||
#else
|
||||
ignore_case_t
|
||||
#endif
|
||||
ignore_case{};
|
||||
|
||||
/** An optional parameter to determine case-sensitivity
|
||||
|
||||
Functions may use parameters of this type
|
||||
to allow the user to optionally indicate
|
||||
that comparisons should be case-insensitive
|
||||
when the value @ref ignore_case is passed.
|
||||
*/
|
||||
class ignore_case_param
|
||||
{
|
||||
/** True if an algorithm should ignore case
|
||||
|
||||
Functions accepting a parameter of type
|
||||
`ignore_case_param` can check `value`
|
||||
to determine if the caller has indicated
|
||||
that comparisons should ignore case.
|
||||
*/
|
||||
bool value_ = false;
|
||||
|
||||
public:
|
||||
/** Constructor
|
||||
|
||||
By default, comparisons are
|
||||
case-sensitive.
|
||||
|
||||
@par Example
|
||||
This function performs case-sensitive
|
||||
comparisons when called with no
|
||||
arguments:
|
||||
@code
|
||||
void f( ignore_case_param = {} );
|
||||
@endcode
|
||||
*/
|
||||
constexpr
|
||||
ignore_case_param() noexcept = default;
|
||||
|
||||
/** Constructor
|
||||
|
||||
Construction from @ref ignore_case
|
||||
indicates that comparisons should
|
||||
be case-insensitive.
|
||||
|
||||
@par Example
|
||||
When @ref ignore_case is passed as
|
||||
an argument, this function ignores
|
||||
case when performing comparisons:
|
||||
@code
|
||||
void f( ignore_case_param = {} );
|
||||
@endcode
|
||||
*/
|
||||
constexpr
|
||||
ignore_case_param(
|
||||
#ifdef BOOST_URL_DOCS
|
||||
__implementation_defined__
|
||||
#else
|
||||
ignore_case_t
|
||||
#endif
|
||||
) noexcept
|
||||
: value_(true)
|
||||
{
|
||||
}
|
||||
|
||||
/** True if an algorithm should ignore case
|
||||
|
||||
Values of type `ignore_case_param`
|
||||
evaluate to true when constructed
|
||||
with the constant @ref ignore_case.
|
||||
Otherwise, they are default-constructed
|
||||
and evaluate to `false`.
|
||||
*/
|
||||
operator
|
||||
bool() const noexcept
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
};
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
//
|
||||
// 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_IMPL_PCT_ENCODED_VIEW_HPP
|
||||
#define BOOST_URL_IMPL_PCT_ENCODED_VIEW_HPP
|
||||
|
||||
#include <boost/url/grammar/type_traits.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
class decode_view::iterator
|
||||
{
|
||||
char const* begin_ = nullptr;
|
||||
char const* pos_ = nullptr;
|
||||
bool space_as_plus_ = true;
|
||||
|
||||
friend decode_view;
|
||||
|
||||
iterator(
|
||||
char const* str,
|
||||
bool space_as_plus) noexcept
|
||||
: begin_(str)
|
||||
, pos_(str)
|
||||
, space_as_plus_(
|
||||
space_as_plus)
|
||||
{
|
||||
}
|
||||
|
||||
// end ctor
|
||||
iterator(
|
||||
char const* str,
|
||||
size_type n,
|
||||
bool space_as_plus) noexcept
|
||||
: begin_(str)
|
||||
, pos_(str + n)
|
||||
, space_as_plus_(space_as_plus)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type = char;
|
||||
using reference = char;
|
||||
using pointer = void const*;
|
||||
using const_reference = char;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
iterator() = default;
|
||||
|
||||
iterator(iterator const&) = default;
|
||||
|
||||
iterator&
|
||||
operator=(iterator const&) = default;
|
||||
|
||||
BOOST_URL_DECL
|
||||
reference
|
||||
operator*() const noexcept;
|
||||
|
||||
iterator&
|
||||
operator++() noexcept
|
||||
{
|
||||
BOOST_ASSERT(pos_ != nullptr);
|
||||
if (*pos_ != '%')
|
||||
++pos_;
|
||||
else
|
||||
pos_ += 3;
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator&
|
||||
operator--() noexcept
|
||||
{
|
||||
BOOST_ASSERT(pos_ != begin_);
|
||||
if (pos_ - begin_ < 3 ||
|
||||
pos_[-3] != '%')
|
||||
--pos_;
|
||||
else
|
||||
pos_ -= 3;
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator
|
||||
operator++(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
iterator
|
||||
operator--(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
--*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
char const*
|
||||
base()
|
||||
{
|
||||
return pos_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
return pos_ == other.pos_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
inline
|
||||
auto
|
||||
decode_view::
|
||||
begin() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
return {p_, space_as_plus_};
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
decode_view::
|
||||
end() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
return {p_, n_, space_as_plus_};
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
decode_view::
|
||||
front() const noexcept ->
|
||||
const_reference
|
||||
{
|
||||
BOOST_ASSERT( !empty() );
|
||||
return *begin();
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
decode_view::
|
||||
back() const noexcept ->
|
||||
const_reference
|
||||
{
|
||||
BOOST_ASSERT( !empty() );
|
||||
return *--end();
|
||||
}
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+278
@@ -0,0 +1,278 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_IMPL_ENCODE_HPP
|
||||
#define BOOST_URL_IMPL_ENCODE_HPP
|
||||
|
||||
#include <boost/url/detail/encode.hpp>
|
||||
#include <boost/url/detail/except.hpp>
|
||||
#include <boost/url/encoding_opts.hpp>
|
||||
#include <boost/url/grammar/charset.hpp>
|
||||
#include <boost/url/grammar/hexdig_chars.hpp>
|
||||
#include <boost/url/grammar/type_traits.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<class CharSet>
|
||||
std::size_t
|
||||
encoded_size(
|
||||
core::string_view s,
|
||||
CharSet const& unreserved,
|
||||
encoding_opts opt) noexcept
|
||||
{
|
||||
/* If you get a compile error here, it
|
||||
means that the value you passed does
|
||||
not meet the requirements stated in
|
||||
the documentation.
|
||||
*/
|
||||
static_assert(
|
||||
grammar::is_charset<CharSet>::value,
|
||||
"Type requirements not met");
|
||||
|
||||
std::size_t n = 0;
|
||||
auto it = s.data();
|
||||
auto const last = it + s.size();
|
||||
|
||||
if(! opt.space_as_plus ||
|
||||
unreserved(' '))
|
||||
{
|
||||
while(it != last)
|
||||
{
|
||||
if(unreserved(*it))
|
||||
n += 1;
|
||||
else
|
||||
n += 3;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while(it != last)
|
||||
{
|
||||
auto c = *it;
|
||||
if(unreserved(c))
|
||||
++n;
|
||||
else if(c == ' ')
|
||||
++n;
|
||||
else
|
||||
n += 3;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<class CharSet>
|
||||
std::size_t
|
||||
encode(
|
||||
char* dest,
|
||||
std::size_t size,
|
||||
core::string_view s,
|
||||
CharSet const& unreserved,
|
||||
encoding_opts opt)
|
||||
{
|
||||
/* If you get a compile error here, it
|
||||
means that the value you passed does
|
||||
not meet the requirements stated in
|
||||
the documentation.
|
||||
*/
|
||||
static_assert(
|
||||
grammar::is_charset<CharSet>::value,
|
||||
"Type requirements not met");
|
||||
|
||||
// '%' must be reserved
|
||||
BOOST_ASSERT(! unreserved('%'));
|
||||
|
||||
char const* const hex =
|
||||
detail::hexdigs[opt.lower_case];
|
||||
auto const encode = [hex](
|
||||
char*& dest,
|
||||
unsigned char c) noexcept
|
||||
{
|
||||
*dest++ = '%';
|
||||
*dest++ = hex[c>>4];
|
||||
*dest++ = hex[c&0xf];
|
||||
};
|
||||
|
||||
auto it = s.data();
|
||||
auto const end = dest + size;
|
||||
auto const last = it + s.size();
|
||||
auto const dest0 = dest;
|
||||
auto const end3 = end - 3;
|
||||
|
||||
if(! opt.space_as_plus)
|
||||
{
|
||||
while(it != last)
|
||||
{
|
||||
if(unreserved(*it))
|
||||
{
|
||||
if(dest == end)
|
||||
return dest - dest0;
|
||||
*dest++ = *it++;
|
||||
continue;
|
||||
}
|
||||
if(dest > end3)
|
||||
return dest - dest0;
|
||||
encode(dest, *it++);
|
||||
}
|
||||
return dest - dest0;
|
||||
}
|
||||
else if(! unreserved(' '))
|
||||
{
|
||||
// VFALCO space is usually reserved,
|
||||
// and we depend on this for an
|
||||
// optimization. if this assert
|
||||
// goes off we can split the loop
|
||||
// below into two versions.
|
||||
BOOST_ASSERT(! unreserved(' '));
|
||||
|
||||
while(it != last)
|
||||
{
|
||||
if(unreserved(*it))
|
||||
{
|
||||
if(dest == end)
|
||||
return dest - dest0;
|
||||
*dest++ = *it++;
|
||||
continue;
|
||||
}
|
||||
if(*it == ' ')
|
||||
{
|
||||
if(dest == end)
|
||||
return dest - dest0;
|
||||
*dest++ = '+';
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
if(dest > end3)
|
||||
return dest - dest0;
|
||||
encode(dest, *it++);
|
||||
}
|
||||
}
|
||||
return dest - dest0;
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
// unsafe encode just
|
||||
// asserts on the output buffer
|
||||
//
|
||||
template<class CharSet>
|
||||
std::size_t
|
||||
encode_unsafe(
|
||||
char* dest,
|
||||
std::size_t size,
|
||||
core::string_view s,
|
||||
CharSet const& unreserved,
|
||||
encoding_opts opt)
|
||||
{
|
||||
// '%' must be reserved
|
||||
BOOST_ASSERT(! unreserved('%'));
|
||||
|
||||
auto it = s.data();
|
||||
auto const last = it + s.size();
|
||||
auto const end = dest + size;
|
||||
ignore_unused(end);
|
||||
|
||||
char const* const hex =
|
||||
detail::hexdigs[opt.lower_case];
|
||||
auto const encode = [end, hex](
|
||||
char*& dest,
|
||||
unsigned char c) noexcept
|
||||
{
|
||||
ignore_unused(end);
|
||||
*dest++ = '%';
|
||||
BOOST_ASSERT(dest != end);
|
||||
*dest++ = hex[c>>4];
|
||||
BOOST_ASSERT(dest != end);
|
||||
*dest++ = hex[c&0xf];
|
||||
};
|
||||
|
||||
auto const dest0 = dest;
|
||||
if(! opt.space_as_plus)
|
||||
{
|
||||
while(it != last)
|
||||
{
|
||||
BOOST_ASSERT(dest != end);
|
||||
if(unreserved(*it))
|
||||
*dest++ = *it++;
|
||||
else
|
||||
encode(dest, *it++);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// VFALCO space is usually reserved,
|
||||
// and we depend on this for an
|
||||
// optimization. if this assert
|
||||
// goes off we can split the loop
|
||||
// below into two versions.
|
||||
BOOST_ASSERT(! unreserved(' '));
|
||||
|
||||
while(it != last)
|
||||
{
|
||||
BOOST_ASSERT(dest != end);
|
||||
if(unreserved(*it))
|
||||
{
|
||||
*dest++ = *it++;
|
||||
}
|
||||
else if(*it == ' ')
|
||||
{
|
||||
*dest++ = '+';
|
||||
++it;
|
||||
}
|
||||
else
|
||||
{
|
||||
encode(dest, *it++);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dest - dest0;
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<
|
||||
class StringToken,
|
||||
class CharSet>
|
||||
BOOST_URL_STRTOK_RETURN
|
||||
encode(
|
||||
core::string_view s,
|
||||
CharSet const& unreserved,
|
||||
encoding_opts opt,
|
||||
StringToken&& token) noexcept
|
||||
{
|
||||
/* If you get a compile error here, it
|
||||
means that the value you passed does
|
||||
not meet the requirements stated in
|
||||
the documentation.
|
||||
*/
|
||||
static_assert(
|
||||
grammar::is_charset<CharSet>::value,
|
||||
"Type requirements not met");
|
||||
|
||||
auto const n = encoded_size(
|
||||
s, unreserved, opt);
|
||||
auto p = token.prepare(n);
|
||||
if(n > 0)
|
||||
encode_unsafe(
|
||||
p, n, s, unreserved, opt);
|
||||
return token.result();
|
||||
}
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_IMPL_ERROR_HPP
|
||||
#define BOOST_URL_IMPL_ERROR_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
|
||||
//-----------------------------------------------
|
||||
namespace system {
|
||||
template<>
|
||||
struct is_error_code_enum<::boost::urls::error>
|
||||
{
|
||||
static bool const value = true;
|
||||
};
|
||||
} // system
|
||||
//-----------------------------------------------
|
||||
|
||||
namespace urls {
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct BOOST_SYMBOL_VISIBLE
|
||||
error_cat_type
|
||||
: system::error_category
|
||||
{
|
||||
BOOST_URL_DECL
|
||||
const char* name(
|
||||
) const noexcept override;
|
||||
|
||||
BOOST_URL_DECL
|
||||
std::string message(
|
||||
int) const override;
|
||||
|
||||
BOOST_URL_DECL
|
||||
char const* message(
|
||||
int, char*, std::size_t
|
||||
) const noexcept override;
|
||||
|
||||
BOOST_URL_DECL
|
||||
system::error_condition
|
||||
default_error_condition(
|
||||
int code) const noexcept override;
|
||||
|
||||
BOOST_SYSTEM_CONSTEXPR error_cat_type() noexcept
|
||||
: error_category(0xbc15399d7a4ce829)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_URL_DECL extern
|
||||
error_cat_type error_cat;
|
||||
|
||||
} // detail
|
||||
|
||||
inline
|
||||
BOOST_SYSTEM_CONSTEXPR
|
||||
system::error_code
|
||||
make_error_code(
|
||||
error ev) noexcept
|
||||
{
|
||||
return system::error_code{
|
||||
static_cast<std::underlying_type<
|
||||
error>::type>(ev),
|
||||
detail::error_cat};
|
||||
}
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
//
|
||||
// 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_IMPL_PARAMS_BASE_HPP
|
||||
#define BOOST_URL_IMPL_PARAMS_BASE_HPP
|
||||
|
||||
#include <boost/url/detail/params_iter_impl.hpp>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
class BOOST_URL_DECL params_base::iterator
|
||||
{
|
||||
detail::params_iter_impl it_;
|
||||
bool space_as_plus_ = true;
|
||||
|
||||
friend class params_base;
|
||||
friend class params_ref;
|
||||
|
||||
iterator(
|
||||
detail::query_ref const& ref,
|
||||
encoding_opts opt) noexcept;
|
||||
|
||||
iterator(
|
||||
detail::query_ref const& impl,
|
||||
encoding_opts opt,
|
||||
int) noexcept;
|
||||
|
||||
iterator(
|
||||
detail::params_iter_impl const& it,
|
||||
encoding_opts opt) noexcept
|
||||
: it_(it)
|
||||
, space_as_plus_(opt.space_as_plus)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type = params_base::value_type;
|
||||
using reference = params_base::reference;
|
||||
using pointer = reference;
|
||||
using difference_type =
|
||||
params_base::difference_type;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
iterator() = default;
|
||||
iterator(iterator const&) = default;
|
||||
iterator& operator=(
|
||||
iterator const&) noexcept = default;
|
||||
|
||||
iterator&
|
||||
operator++() noexcept
|
||||
{
|
||||
it_.increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator
|
||||
operator++(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
iterator&
|
||||
operator--() noexcept
|
||||
{
|
||||
it_.decrement();
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator
|
||||
operator--(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
--*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const;
|
||||
|
||||
// the return value is too expensive
|
||||
pointer operator->() const = delete;
|
||||
|
||||
bool
|
||||
operator==(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
return it_.equal(other.it_);
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
return ! it_.equal(other.it_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
//
|
||||
// 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_IMPL_PARAMS_ENCODED_BASE_HPP
|
||||
#define BOOST_URL_IMPL_PARAMS_ENCODED_BASE_HPP
|
||||
|
||||
#include <boost/url/detail/params_iter_impl.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
class params_ref;
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
class params_encoded_base::iterator
|
||||
{
|
||||
detail::params_iter_impl it_;
|
||||
|
||||
friend class params_encoded_base;
|
||||
friend class params_encoded_ref;
|
||||
|
||||
iterator(detail::query_ref const& ref) noexcept;
|
||||
iterator(detail::query_ref const& ref, int) noexcept;
|
||||
iterator(
|
||||
detail::params_iter_impl const& it)
|
||||
: it_(it)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type =
|
||||
params_encoded_base::value_type;
|
||||
using reference =
|
||||
params_encoded_base::reference;
|
||||
using pointer = reference;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
iterator() = default;
|
||||
iterator(iterator const&) = default;
|
||||
iterator& operator=(
|
||||
iterator const&) = default;
|
||||
|
||||
iterator&
|
||||
operator++() noexcept
|
||||
{
|
||||
it_.increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator
|
||||
operator++(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
iterator&
|
||||
operator--() noexcept
|
||||
{
|
||||
it_.decrement();
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator
|
||||
operator--(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
--*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
return it_.dereference();
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const
|
||||
{
|
||||
return it_.dereference();
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator==(
|
||||
iterator const& it0,
|
||||
iterator const& it1) noexcept
|
||||
{
|
||||
return it0.it_.equal(it1.it_);
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator!=(
|
||||
iterator const& it0,
|
||||
iterator const& it1) noexcept
|
||||
{
|
||||
return ! it0.it_.equal(it1.it_);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// Observers
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
inline
|
||||
bool
|
||||
params_encoded_base::
|
||||
contains(
|
||||
pct_string_view key,
|
||||
ignore_case_param ic) const noexcept
|
||||
{
|
||||
return find_impl(
|
||||
begin().it_, key, ic) != end();
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
params_encoded_base::
|
||||
find(
|
||||
pct_string_view key,
|
||||
ignore_case_param ic) const noexcept ->
|
||||
iterator
|
||||
{
|
||||
return find_impl(
|
||||
begin().it_, key, ic);
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
params_encoded_base::
|
||||
find(
|
||||
iterator it,
|
||||
pct_string_view key,
|
||||
ignore_case_param ic) const noexcept ->
|
||||
iterator
|
||||
{
|
||||
return find_impl(
|
||||
it.it_, key, ic);
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
params_encoded_base::
|
||||
find_last(
|
||||
pct_string_view key,
|
||||
ignore_case_param ic) const noexcept ->
|
||||
iterator
|
||||
{
|
||||
return find_last_impl(
|
||||
end().it_, key, ic);
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
params_encoded_base::
|
||||
find_last(
|
||||
iterator it,
|
||||
pct_string_view key,
|
||||
ignore_case_param ic) const noexcept ->
|
||||
iterator
|
||||
{
|
||||
return find_last_impl(
|
||||
it.it_, key, ic);
|
||||
}
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
//
|
||||
// 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_IMPL_PARAMS_ENCODED_REF_HPP
|
||||
#define BOOST_URL_IMPL_PARAMS_ENCODED_REF_HPP
|
||||
|
||||
#include <boost/url/detail/except.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// Modifiers
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
inline
|
||||
void
|
||||
params_encoded_ref::
|
||||
clear() noexcept
|
||||
{
|
||||
u_->remove_query();
|
||||
}
|
||||
|
||||
template<class FwdIt>
|
||||
void
|
||||
params_encoded_ref::
|
||||
assign(FwdIt first, FwdIt last)
|
||||
{
|
||||
/* If you get a compile error here, it
|
||||
means that the iterators you passed
|
||||
do not meet the requirements stated
|
||||
in the documentation.
|
||||
*/
|
||||
static_assert(
|
||||
std::is_convertible<
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::reference,
|
||||
param_view>::value,
|
||||
"Type requirements not met");
|
||||
|
||||
assign(first, last,
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::iterator_category{});
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
params_encoded_ref::
|
||||
append(
|
||||
param_pct_view const& p) ->
|
||||
iterator
|
||||
{
|
||||
return insert(end(), p);
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
params_encoded_ref::
|
||||
append(
|
||||
std::initializer_list<
|
||||
param_pct_view> init) ->
|
||||
iterator
|
||||
{
|
||||
return insert(end(), init);
|
||||
}
|
||||
|
||||
template<class FwdIt>
|
||||
auto
|
||||
params_encoded_ref::
|
||||
append(
|
||||
FwdIt first, FwdIt last) ->
|
||||
iterator
|
||||
{
|
||||
/* If you get a compile error here, it
|
||||
means that the iterators you passed
|
||||
do not meet the requirements stated
|
||||
in the documentation.
|
||||
*/
|
||||
static_assert(
|
||||
std::is_convertible<
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::reference,
|
||||
param_view>::value,
|
||||
"Type requirements not met");
|
||||
|
||||
return insert(
|
||||
end(), first, last);
|
||||
}
|
||||
|
||||
template<class FwdIt>
|
||||
auto
|
||||
params_encoded_ref::
|
||||
insert(
|
||||
iterator before,
|
||||
FwdIt first,
|
||||
FwdIt last) ->
|
||||
iterator
|
||||
{
|
||||
/* If you get a compile error here, it
|
||||
means that the iterators you passed
|
||||
do not meet the requirements stated
|
||||
in the documentation.
|
||||
*/
|
||||
static_assert(
|
||||
std::is_convertible<
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::reference,
|
||||
param_view>::value,
|
||||
"Type requirements not met");
|
||||
|
||||
return insert(
|
||||
before,
|
||||
first,
|
||||
last,
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::iterator_category{});
|
||||
}
|
||||
|
||||
template<class FwdIt>
|
||||
auto
|
||||
params_encoded_ref::
|
||||
replace(
|
||||
iterator from,
|
||||
iterator to,
|
||||
FwdIt first,
|
||||
FwdIt last) ->
|
||||
iterator
|
||||
{
|
||||
/* If you get a compile error here, it
|
||||
means that the iterators you passed
|
||||
do not meet the requirements stated
|
||||
in the documentation.
|
||||
*/
|
||||
static_assert(
|
||||
std::is_convertible<
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::reference,
|
||||
param_view>::value,
|
||||
"Type requirements not met");
|
||||
|
||||
return u_->edit_params(
|
||||
from.it_, to.it_,
|
||||
detail::make_params_encoded_iter(
|
||||
first, last));
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// implementation
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
template<class FwdIt>
|
||||
void
|
||||
params_encoded_ref::
|
||||
assign(FwdIt first, FwdIt last,
|
||||
std::forward_iterator_tag)
|
||||
{
|
||||
u_->edit_params(
|
||||
begin().it_,
|
||||
end().it_,
|
||||
detail::make_params_encoded_iter(
|
||||
first, last));
|
||||
}
|
||||
|
||||
template<class FwdIt>
|
||||
auto
|
||||
params_encoded_ref::
|
||||
insert(
|
||||
iterator before,
|
||||
FwdIt first,
|
||||
FwdIt last,
|
||||
std::forward_iterator_tag) ->
|
||||
iterator
|
||||
{
|
||||
return u_->edit_params(
|
||||
before.it_,
|
||||
before.it_,
|
||||
detail::make_params_encoded_iter(
|
||||
first, last));
|
||||
}
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+240
@@ -0,0 +1,240 @@
|
||||
//
|
||||
// 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_IMPL_PARAMS_REF_HPP
|
||||
#define BOOST_URL_IMPL_PARAMS_REF_HPP
|
||||
|
||||
#include <boost/url/params_view.hpp>
|
||||
#include <boost/url/detail/any_params_iter.hpp>
|
||||
#include <boost/url/detail/except.hpp>
|
||||
#include <boost/url/grammar/recycled.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
inline
|
||||
params_ref::
|
||||
params_ref(
|
||||
url_base& u,
|
||||
encoding_opts opt) noexcept
|
||||
: params_base(u.impl_, opt)
|
||||
, u_(&u)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// Special Members
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
inline
|
||||
params_ref::
|
||||
params_ref(
|
||||
params_ref const& other,
|
||||
encoding_opts opt) noexcept
|
||||
: params_ref(*other.u_, opt)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
params_ref::
|
||||
operator=(std::initializer_list<
|
||||
param_view> init) ->
|
||||
params_ref&
|
||||
{
|
||||
assign(init);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// Modifiers
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
inline
|
||||
void
|
||||
params_ref::
|
||||
clear() noexcept
|
||||
{
|
||||
u_->remove_query();
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<class FwdIt>
|
||||
void
|
||||
params_ref::
|
||||
assign(FwdIt first, FwdIt last)
|
||||
{
|
||||
/* If you get a compile error here, it
|
||||
means that the iterators you passed
|
||||
do not meet the requirements stated
|
||||
in the documentation.
|
||||
*/
|
||||
static_assert(
|
||||
std::is_convertible<
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::reference,
|
||||
param_view>::value,
|
||||
"Type requirements not met");
|
||||
|
||||
assign(first, last,
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::iterator_category{});
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
params_ref::
|
||||
append(
|
||||
param_view const& p) ->
|
||||
iterator
|
||||
{
|
||||
return insert(end(), p);
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
params_ref::
|
||||
append(
|
||||
std::initializer_list<
|
||||
param_view> init) ->
|
||||
iterator
|
||||
{
|
||||
return insert(end(), init);
|
||||
}
|
||||
|
||||
template<class FwdIt>
|
||||
auto
|
||||
params_ref::
|
||||
append(FwdIt first, FwdIt last) ->
|
||||
iterator
|
||||
{
|
||||
/* If you get a compile error here, it
|
||||
means that the iterators you passed
|
||||
do not meet the requirements stated
|
||||
in the documentation.
|
||||
*/
|
||||
static_assert(
|
||||
std::is_convertible<
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::reference,
|
||||
param_view>::value,
|
||||
"Type requirements not met");
|
||||
|
||||
return insert(
|
||||
end(), first, last);
|
||||
}
|
||||
|
||||
template<class FwdIt>
|
||||
auto
|
||||
params_ref::
|
||||
insert(
|
||||
iterator before,
|
||||
FwdIt first,
|
||||
FwdIt last) ->
|
||||
iterator
|
||||
{
|
||||
/* If you get a compile error here, it
|
||||
means that the iterators you passed
|
||||
do not meet the requirements stated
|
||||
in the documentation.
|
||||
*/
|
||||
static_assert(
|
||||
std::is_convertible<
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::reference,
|
||||
param_view>::value,
|
||||
"Type requirements not met");
|
||||
|
||||
return insert(
|
||||
before,
|
||||
first,
|
||||
last,
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::iterator_category{});
|
||||
}
|
||||
|
||||
template<class FwdIt>
|
||||
auto
|
||||
params_ref::
|
||||
replace(
|
||||
iterator from,
|
||||
iterator to,
|
||||
FwdIt first,
|
||||
FwdIt last) ->
|
||||
iterator
|
||||
{
|
||||
/* If you get a compile error here, it
|
||||
means that the iterators you passed
|
||||
do not meet the requirements stated
|
||||
in the documentation.
|
||||
*/
|
||||
static_assert(
|
||||
std::is_convertible<
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::reference,
|
||||
param_view>::value,
|
||||
"Type requirements not met");
|
||||
|
||||
return iterator(
|
||||
u_->edit_params(
|
||||
from.it_, to.it_,
|
||||
detail::make_params_iter(
|
||||
first, last)),
|
||||
opt_);
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// implementation
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
template<class FwdIt>
|
||||
void
|
||||
params_ref::
|
||||
assign(FwdIt first, FwdIt last,
|
||||
std::forward_iterator_tag)
|
||||
{
|
||||
u_->edit_params(
|
||||
begin().it_,
|
||||
end().it_,
|
||||
detail::make_params_iter(
|
||||
first, last));
|
||||
}
|
||||
|
||||
template<class FwdIt>
|
||||
auto
|
||||
params_ref::
|
||||
insert(
|
||||
iterator before,
|
||||
FwdIt first,
|
||||
FwdIt last,
|
||||
std::forward_iterator_tag) ->
|
||||
iterator
|
||||
{
|
||||
return iterator(
|
||||
u_->edit_params(
|
||||
before.it_,
|
||||
before.it_,
|
||||
detail::make_params_iter(
|
||||
first, last)),
|
||||
opt_);
|
||||
}
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
//
|
||||
// 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_IMPL_SEGMENTS_BASE_HPP
|
||||
#define BOOST_URL_IMPL_SEGMENTS_BASE_HPP
|
||||
|
||||
#include <boost/url/detail/segments_iter_impl.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
class segments_base::iterator
|
||||
{
|
||||
detail::segments_iter_impl it_;
|
||||
|
||||
friend class segments_base;
|
||||
friend class segments_ref;
|
||||
|
||||
iterator(detail::path_ref const&) noexcept;
|
||||
iterator(detail::path_ref const&, int) noexcept;
|
||||
|
||||
iterator(
|
||||
detail::segments_iter_impl const& it) noexcept
|
||||
: it_(it)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type = segments_base::value_type;
|
||||
using reference = segments_base::reference;
|
||||
using pointer = reference;
|
||||
using difference_type =
|
||||
segments_base::difference_type;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
iterator() = default;
|
||||
iterator(iterator const&) = default;
|
||||
iterator& operator=(
|
||||
iterator const&) noexcept = default;
|
||||
|
||||
BOOST_URL_DECL
|
||||
reference
|
||||
operator*() const;
|
||||
|
||||
// the return value is too expensive
|
||||
pointer operator->() const = delete;
|
||||
|
||||
iterator&
|
||||
operator++() noexcept
|
||||
{
|
||||
it_.increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator&
|
||||
operator--() noexcept
|
||||
{
|
||||
it_.decrement();
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator
|
||||
operator++(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
iterator
|
||||
operator--(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
--*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
return it_.equal(other.it_);
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
return ! it_.equal(other.it_);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
inline
|
||||
std::string
|
||||
segments_base::
|
||||
front() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(! empty());
|
||||
return *begin();
|
||||
}
|
||||
|
||||
inline
|
||||
std::string
|
||||
segments_base::
|
||||
back() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(! empty());
|
||||
return *--end();
|
||||
}
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
//
|
||||
// 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_IMPL_SEGMENTS_ENCODED_BASE_HPP
|
||||
#define BOOST_URL_IMPL_SEGMENTS_ENCODED_BASE_HPP
|
||||
|
||||
#include <boost/url/detail/segments_iter_impl.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
class segments_encoded_base::iterator
|
||||
{
|
||||
detail::segments_iter_impl it_;
|
||||
|
||||
friend class url_base;
|
||||
friend class segments_encoded_base;
|
||||
friend class segments_encoded_ref;
|
||||
|
||||
iterator(detail::path_ref const&) noexcept;
|
||||
iterator(detail::path_ref const&, int) noexcept;
|
||||
|
||||
iterator(
|
||||
detail::segments_iter_impl const& it) noexcept
|
||||
: it_(it)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type =
|
||||
segments_encoded_base::value_type;
|
||||
using reference =
|
||||
segments_encoded_base::reference;
|
||||
using pointer = reference;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
iterator() = default;
|
||||
iterator(iterator const&) = default;
|
||||
iterator& operator=(
|
||||
iterator const&) = default;
|
||||
|
||||
reference
|
||||
operator*() const noexcept
|
||||
{
|
||||
return it_.dereference();
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const noexcept
|
||||
{
|
||||
return it_.dereference();
|
||||
}
|
||||
|
||||
iterator&
|
||||
operator++() noexcept
|
||||
{
|
||||
it_.increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator&
|
||||
operator--() noexcept
|
||||
{
|
||||
it_.decrement();
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator
|
||||
operator++(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
iterator
|
||||
operator--(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
--*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
return it_.equal(other.it_);
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
return ! it_.equal(other.it_);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
inline
|
||||
pct_string_view
|
||||
segments_encoded_base::
|
||||
front() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(! empty());
|
||||
return *begin();
|
||||
}
|
||||
|
||||
inline
|
||||
pct_string_view
|
||||
segments_encoded_base::
|
||||
back() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(! empty());
|
||||
return *--end();
|
||||
}
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
//
|
||||
// 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_IMPL_SEGMENTS_ENCODED_REF_HPP
|
||||
#define BOOST_URL_IMPL_SEGMENTS_ENCODED_REF_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/detail/segments_iter_impl.hpp>
|
||||
#include <boost/url/detail/any_segments_iter.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// Modifiers
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
inline
|
||||
void
|
||||
segments_encoded_ref::
|
||||
clear() noexcept
|
||||
{
|
||||
erase(begin(), end());
|
||||
}
|
||||
|
||||
template<class FwdIt>
|
||||
void
|
||||
segments_encoded_ref::
|
||||
assign(
|
||||
FwdIt first, FwdIt last)
|
||||
{
|
||||
/* If you get a compile error here, it
|
||||
means that the iterators you passed
|
||||
do not meet the requirements stated
|
||||
in the documentation.
|
||||
*/
|
||||
static_assert(
|
||||
std::is_convertible<
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::reference,
|
||||
core::string_view>::value,
|
||||
"Type requirements not met");
|
||||
|
||||
u_->edit_segments(
|
||||
begin().it_,
|
||||
end().it_,
|
||||
detail::make_segments_encoded_iter(
|
||||
first, last));
|
||||
}
|
||||
|
||||
template<class FwdIt>
|
||||
auto
|
||||
segments_encoded_ref::
|
||||
insert(
|
||||
iterator before,
|
||||
FwdIt first,
|
||||
FwdIt last) ->
|
||||
iterator
|
||||
{
|
||||
/* If you get a compile error here, it
|
||||
means that the iterators you passed
|
||||
do not meet the requirements stated
|
||||
in the documentation.
|
||||
*/
|
||||
static_assert(
|
||||
std::is_convertible<
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::reference,
|
||||
core::string_view>::value,
|
||||
"Type requirements not met");
|
||||
|
||||
return insert(
|
||||
before,
|
||||
first,
|
||||
last,
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::iterator_category{});
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
segments_encoded_ref::
|
||||
erase(
|
||||
iterator pos) noexcept ->
|
||||
iterator
|
||||
{
|
||||
return erase(pos, std::next(pos));
|
||||
}
|
||||
|
||||
template<class FwdIt>
|
||||
auto
|
||||
segments_encoded_ref::
|
||||
replace(
|
||||
iterator from,
|
||||
iterator to,
|
||||
FwdIt first,
|
||||
FwdIt last) ->
|
||||
iterator
|
||||
{
|
||||
/* If you get a compile error here, it
|
||||
means that the iterators you passed
|
||||
do not meet the requirements stated
|
||||
in the documentation.
|
||||
*/
|
||||
static_assert(
|
||||
std::is_convertible<
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::reference,
|
||||
core::string_view>::value,
|
||||
"Type requirements not met");
|
||||
|
||||
return u_->edit_segments(
|
||||
from.it_,
|
||||
to.it_,
|
||||
detail::make_segments_encoded_iter(
|
||||
first, last));
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
inline
|
||||
void
|
||||
segments_encoded_ref::
|
||||
push_back(
|
||||
pct_string_view s)
|
||||
{
|
||||
insert(end(), s);
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
segments_encoded_ref::
|
||||
pop_back() noexcept
|
||||
{
|
||||
erase(std::prev(end()));
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<class FwdIt>
|
||||
auto
|
||||
segments_encoded_ref::
|
||||
insert(
|
||||
iterator before,
|
||||
FwdIt first,
|
||||
FwdIt last,
|
||||
std::forward_iterator_tag) ->
|
||||
iterator
|
||||
{
|
||||
return u_->edit_segments(
|
||||
before.it_,
|
||||
before.it_,
|
||||
detail::make_segments_encoded_iter(
|
||||
first, last));
|
||||
}
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
//
|
||||
// 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_IMPL_SEGMENTS_REF_HPP
|
||||
#define BOOST_URL_IMPL_SEGMENTS_REF_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/detail/any_segments_iter.hpp>
|
||||
#include <boost/url/detail/segments_iter_impl.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
//------------------------------------------------
|
||||
//
|
||||
// Modifiers
|
||||
//
|
||||
//------------------------------------------------
|
||||
|
||||
inline
|
||||
void
|
||||
segments_ref::
|
||||
clear() noexcept
|
||||
{
|
||||
erase(begin(), end());
|
||||
}
|
||||
|
||||
template<class FwdIt>
|
||||
void
|
||||
segments_ref::
|
||||
assign(FwdIt first, FwdIt last)
|
||||
{
|
||||
/* If you get a compile error here, it
|
||||
means that the iterators you passed
|
||||
do not meet the requirements stated
|
||||
in the documentation.
|
||||
*/
|
||||
static_assert(
|
||||
std::is_convertible<
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::reference,
|
||||
core::string_view>::value,
|
||||
"Type requirements not met");
|
||||
|
||||
u_->edit_segments(
|
||||
begin().it_,
|
||||
end().it_,
|
||||
detail::make_segments_iter(
|
||||
first, last));
|
||||
}
|
||||
|
||||
template<class FwdIt>
|
||||
auto
|
||||
segments_ref::
|
||||
insert(
|
||||
iterator before,
|
||||
FwdIt first,
|
||||
FwdIt last) ->
|
||||
iterator
|
||||
{
|
||||
/* If you get a compile error here, it
|
||||
means that the iterators you passed
|
||||
do not meet the requirements stated
|
||||
in the documentation.
|
||||
*/
|
||||
static_assert(
|
||||
std::is_convertible<
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::reference,
|
||||
core::string_view>::value,
|
||||
"Type requirements not met");
|
||||
|
||||
return insert(
|
||||
before,
|
||||
first,
|
||||
last,
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::iterator_category{});
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
segments_ref::
|
||||
erase(
|
||||
iterator pos) noexcept ->
|
||||
iterator
|
||||
{
|
||||
return erase(pos, std::next(pos));
|
||||
}
|
||||
|
||||
template<class FwdIt>
|
||||
auto
|
||||
segments_ref::
|
||||
replace(
|
||||
iterator from,
|
||||
iterator to,
|
||||
FwdIt first,
|
||||
FwdIt last) ->
|
||||
iterator
|
||||
{
|
||||
/* If you get a compile error here, it
|
||||
means that the iterators you passed
|
||||
do not meet the requirements stated
|
||||
in the documentation.
|
||||
*/
|
||||
static_assert(
|
||||
std::is_convertible<
|
||||
typename std::iterator_traits<
|
||||
FwdIt>::reference,
|
||||
core::string_view>::value,
|
||||
"Type requirements not met");
|
||||
|
||||
return u_->edit_segments(
|
||||
from.it_,
|
||||
to.it_,
|
||||
detail::make_segments_iter(
|
||||
first, last));
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
inline
|
||||
void
|
||||
segments_ref::
|
||||
push_back(
|
||||
core::string_view s)
|
||||
{
|
||||
insert(end(), s);
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
segments_ref::
|
||||
pop_back() noexcept
|
||||
{
|
||||
erase(std::prev(end()));
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<class FwdIt>
|
||||
auto
|
||||
segments_ref::
|
||||
insert(
|
||||
iterator before,
|
||||
FwdIt first,
|
||||
FwdIt last,
|
||||
std::forward_iterator_tag) ->
|
||||
iterator
|
||||
{
|
||||
return u_->edit_segments(
|
||||
before.it_,
|
||||
before.it_,
|
||||
detail::make_segments_iter(
|
||||
first, last));
|
||||
}
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+344
@@ -0,0 +1,344 @@
|
||||
//
|
||||
// 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_IPV4_ADDRESS_HPP
|
||||
#define BOOST_URL_IPV4_ADDRESS_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/error.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/url/grammar/string_token.hpp>
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <iosfwd>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
/** An IP version 4 style address.
|
||||
|
||||
Objects of this type are used to construct,
|
||||
parse, and manipulate IP version 6 addresses.
|
||||
|
||||
@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 <a href="https://en.wikipedia.org/wiki/IPv4"
|
||||
>IPv4 (Wikipedia)</a>
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
|
||||
>3.2.2. Host (rfc3986)</a>
|
||||
|
||||
@see
|
||||
@ref parse_ipv4_address,
|
||||
@ref ipv6_address.
|
||||
*/
|
||||
class ipv4_address
|
||||
{
|
||||
public:
|
||||
/** The number of characters in the longest possible IPv4 string.
|
||||
|
||||
The longest ipv4 address string is "255.255.255.255".
|
||||
*/
|
||||
static
|
||||
constexpr
|
||||
std::size_t max_str_len = 15;
|
||||
|
||||
/** The type used to represent an address as an unsigned integer
|
||||
*/
|
||||
using uint_type =
|
||||
std::uint_least32_t;
|
||||
|
||||
/** The type used to represent an address as an array of bytes
|
||||
*/
|
||||
using bytes_type =
|
||||
std::array<unsigned char, 4>;
|
||||
|
||||
/** Constructor.
|
||||
*/
|
||||
ipv4_address() = default;
|
||||
|
||||
/** Constructor.
|
||||
*/
|
||||
ipv4_address(
|
||||
ipv4_address const&) = default;
|
||||
|
||||
/** Copy Assignment.
|
||||
*/
|
||||
ipv4_address&
|
||||
operator=(
|
||||
ipv4_address const&) = default;
|
||||
|
||||
//
|
||||
//---
|
||||
//
|
||||
|
||||
/** Construct from an unsigned integer.
|
||||
|
||||
This function constructs an address from
|
||||
the unsigned integer `u`, where the most
|
||||
significant byte forms the first octet
|
||||
of the resulting address.
|
||||
|
||||
@param u The integer to construct from.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
explicit
|
||||
ipv4_address(
|
||||
uint_type u) noexcept;
|
||||
|
||||
/** Construct from an array of bytes.
|
||||
|
||||
This function constructs an address
|
||||
from the array in `bytes`, which is
|
||||
interpreted in big-endian.
|
||||
|
||||
@param bytes The value to construct from.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
explicit
|
||||
ipv4_address(
|
||||
bytes_type const& bytes) noexcept;
|
||||
|
||||
/** Construct from a string.
|
||||
|
||||
This function constructs an address from
|
||||
the string `s`, which must contain a valid
|
||||
IPv4 address string or else an exception
|
||||
is thrown.
|
||||
|
||||
@note For a non-throwing parse function,
|
||||
use @ref parse_ipv4_address.
|
||||
|
||||
@par Exception Safety
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@throw system_error
|
||||
The input failed to parse correctly.
|
||||
|
||||
@param s The string to parse.
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
|
||||
>3.2.2. Host (rfc3986)</a>
|
||||
|
||||
@see
|
||||
@ref parse_ipv4_address.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
explicit
|
||||
ipv4_address(
|
||||
core::string_view s);
|
||||
|
||||
/** Return the address as bytes, in network byte order.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
bytes_type
|
||||
to_bytes() const noexcept;
|
||||
|
||||
/** Return the address as an unsigned integer.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
uint_type
|
||||
to_uint() const noexcept;
|
||||
|
||||
/** Return the address as a string in dotted decimal format
|
||||
|
||||
When called with no arguments, the
|
||||
return type is `std::string`.
|
||||
Otherwise, the return type and style
|
||||
of output is determined by which string
|
||||
token is passed.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( ipv4_address(0x01020304).to_string() == "1.2.3.4" );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
Calls to allocate may throw.
|
||||
String tokens may throw exceptions.
|
||||
|
||||
@return The return type of the string token.
|
||||
If the token parameter is omitted, then
|
||||
a new `std::string` is returned.
|
||||
Otherwise, the function return type
|
||||
is the result type of the token.
|
||||
|
||||
@param token An optional string token.
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.2">
|
||||
2.2. Text Representation of Addresses (rfc4291)</a>
|
||||
*/
|
||||
template<BOOST_URL_STRTOK_TPARAM>
|
||||
BOOST_URL_STRTOK_RETURN
|
||||
to_string(
|
||||
BOOST_URL_STRTOK_ARG(token)) const
|
||||
{
|
||||
to_string_impl(token);
|
||||
return token.result();
|
||||
}
|
||||
|
||||
/** Write a dotted decimal string representing the address to a buffer
|
||||
|
||||
The resulting buffer is not null-terminated.
|
||||
|
||||
@throw std::length_error `dest_size < ipv4_address::max_str_len`
|
||||
|
||||
@return The formatted string
|
||||
|
||||
@param dest The buffer in which to write,
|
||||
which must have at least `dest_size` space.
|
||||
|
||||
@param dest_size The size of the output buffer.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
core::string_view
|
||||
to_buffer(
|
||||
char* dest,
|
||||
std::size_t dest_size) const;
|
||||
|
||||
/** Return true if the address is a loopback address
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
bool
|
||||
is_loopback() const noexcept;
|
||||
|
||||
/** Return true if the address is unspecified
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
bool
|
||||
is_unspecified() const noexcept;
|
||||
|
||||
/** Return true if the address is a multicast address
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
bool
|
||||
is_multicast() const noexcept;
|
||||
|
||||
/** Return true if two addresses are equal
|
||||
*/
|
||||
friend
|
||||
bool
|
||||
operator==(
|
||||
ipv4_address const& a1,
|
||||
ipv4_address const& a2) noexcept
|
||||
{
|
||||
return a1.addr_ == a2.addr_;
|
||||
}
|
||||
|
||||
/** Return true if two addresses are not equal
|
||||
*/
|
||||
friend
|
||||
bool
|
||||
operator!=(
|
||||
ipv4_address const& a1,
|
||||
ipv4_address const& a2) noexcept
|
||||
{
|
||||
return a1.addr_ != a2.addr_;
|
||||
}
|
||||
|
||||
/** Return an address object that represents any address
|
||||
*/
|
||||
static
|
||||
ipv4_address
|
||||
any() noexcept
|
||||
{
|
||||
return ipv4_address();
|
||||
}
|
||||
|
||||
/** Return an address object that represents the loopback address
|
||||
*/
|
||||
static
|
||||
ipv4_address
|
||||
loopback() noexcept
|
||||
{
|
||||
return ipv4_address(0x7F000001);
|
||||
}
|
||||
|
||||
/** Return an address object that represents the broadcast address
|
||||
*/
|
||||
static
|
||||
ipv4_address
|
||||
broadcast() noexcept
|
||||
{
|
||||
return ipv4_address(0xFFFFFFFF);
|
||||
}
|
||||
|
||||
// hidden friend
|
||||
friend
|
||||
std::ostream&
|
||||
operator<<(
|
||||
std::ostream& os,
|
||||
ipv4_address const& addr)
|
||||
{
|
||||
char buf[ipv4_address::max_str_len];
|
||||
os << addr.to_buffer(buf, sizeof(buf));
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ipv6_address;
|
||||
|
||||
BOOST_URL_DECL
|
||||
std::size_t
|
||||
print_impl(
|
||||
char* dest) const noexcept;
|
||||
|
||||
BOOST_URL_DECL
|
||||
void
|
||||
to_string_impl(
|
||||
string_token::arg& t) const;
|
||||
|
||||
uint_type addr_ = 0;
|
||||
};
|
||||
|
||||
/** Format the address to an output stream.
|
||||
|
||||
IPv4 addresses written to output streams
|
||||
are written in their dotted decimal format.
|
||||
|
||||
@param os The output stream.
|
||||
|
||||
@param addr The address to format.
|
||||
*/
|
||||
std::ostream&
|
||||
operator<<(
|
||||
std::ostream& os,
|
||||
ipv4_address const& addr);
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Return an IPv4 address from an IP address string in dotted decimal form
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
system::result<ipv4_address>
|
||||
parse_ipv4_address(
|
||||
core::string_view s) noexcept;
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+398
@@ -0,0 +1,398 @@
|
||||
//
|
||||
// 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_IPV6_ADDRESS_HPP
|
||||
#define BOOST_URL_IPV6_ADDRESS_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/error.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/url/grammar/string_token.hpp>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <iosfwd>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
class ipv4_address;
|
||||
#endif
|
||||
|
||||
/** An IP version 6 style address.
|
||||
|
||||
Objects of this type are used to construct,
|
||||
parse, and manipulate IP version 6 addresses.
|
||||
|
||||
@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 <a href="https://datatracker.ietf.org/doc/html/rfc4291"
|
||||
>IP Version 6 Addressing Architecture (rfc4291)</a>
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
|
||||
>3.2.2. Host (rfc3986)</a>
|
||||
|
||||
@see
|
||||
@ref ipv4_address,
|
||||
@ref parse_ipv6_address.
|
||||
*/
|
||||
class ipv6_address
|
||||
{
|
||||
public:
|
||||
/** The number of characters in the longest possible IPv6 string.
|
||||
|
||||
The longest IPv6 address is:
|
||||
@code
|
||||
ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
|
||||
@endcode
|
||||
|
||||
@see
|
||||
@ref to_buffer.
|
||||
*/
|
||||
// ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
|
||||
// ::ffff:255.255.255.255
|
||||
// 12345678901234567890123456789012345678901234567890
|
||||
// 1 2 3 4
|
||||
static
|
||||
constexpr
|
||||
std::size_t max_str_len = 49;
|
||||
|
||||
/** The type used to represent an address as an array of bytes.
|
||||
|
||||
Octets are stored in network byte order.
|
||||
*/
|
||||
using bytes_type = std::array<
|
||||
unsigned char, 16>;
|
||||
|
||||
/** Constructor.
|
||||
|
||||
Default constructed objects represent
|
||||
the unspecified address.
|
||||
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.2"
|
||||
>2.5.2. The Unspecified Address</a>
|
||||
|
||||
@see
|
||||
@ref is_unspecified
|
||||
*/
|
||||
ipv6_address() = default;
|
||||
|
||||
/** Constructor.
|
||||
*/
|
||||
ipv6_address(
|
||||
ipv6_address const&) = default;
|
||||
|
||||
/** Copy Assignment
|
||||
*/
|
||||
ipv6_address&
|
||||
operator=(
|
||||
ipv6_address const&) = default;
|
||||
|
||||
/** Construct from an array of bytes.
|
||||
|
||||
This function constructs an address
|
||||
from the array in `bytes`, which is
|
||||
interpreted in big-endian.
|
||||
|
||||
@param bytes The value to construct from.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
ipv6_address(
|
||||
bytes_type const& bytes) noexcept;
|
||||
|
||||
/** Construct from an IPv4 address.
|
||||
|
||||
This function constructs an IPv6 address
|
||||
from the IPv4 address `addr`. The resulting
|
||||
address is an IPv4-Mapped IPv6 Address.
|
||||
|
||||
@param addr The address to construct from.
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2"
|
||||
>2.5.5.2. IPv4-Mapped IPv6 Address (rfc4291)</a>
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
ipv6_address(
|
||||
ipv4_address const& addr) noexcept;
|
||||
|
||||
/** Construct from a string.
|
||||
|
||||
This function constructs an address from
|
||||
the string `s`, which must contain a valid
|
||||
IPv6 address string or else an exception
|
||||
is thrown.
|
||||
|
||||
@note For a non-throwing parse function,
|
||||
use @ref parse_ipv6_address.
|
||||
|
||||
@par Exception Safety
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@throw system_error
|
||||
The input failed to parse correctly.
|
||||
|
||||
@param s The string to parse.
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
|
||||
>3.2.2. Host (rfc3986)</a>
|
||||
|
||||
@see
|
||||
@ref parse_ipv6_address.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
ipv6_address(
|
||||
core::string_view s);
|
||||
|
||||
/** Return the address as bytes, in network byte order
|
||||
*/
|
||||
bytes_type
|
||||
to_bytes() const noexcept
|
||||
{
|
||||
return addr_;
|
||||
}
|
||||
|
||||
/** Return the address as a string.
|
||||
|
||||
The returned string does not
|
||||
contain surrounding square brackets.
|
||||
|
||||
When called with no arguments, the
|
||||
return type is `std::string`.
|
||||
Otherwise, the return type and style
|
||||
of output is determined by which string
|
||||
token is passed.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
ipv6_address::bytes_type b = {{
|
||||
0, 1, 0, 2, 0, 3, 0, 4,
|
||||
0, 5, 0, 6, 0, 7, 0, 8 }};
|
||||
ipv6_address a(b);
|
||||
assert(a.to_string() == "1:2:3:4:5:6:7:8");
|
||||
assert( ipv4_address(0x01020304).to_string() == "1.2.3.4" );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
Calls to allocate may throw.
|
||||
String tokens may throw exceptions.
|
||||
|
||||
@return The return type of the string token.
|
||||
If the token parameter is omitted, then
|
||||
a new `std::string` is returned.
|
||||
Otherwise, the function return type
|
||||
is the result type of the token.
|
||||
|
||||
@param token An optional string token.
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.2">
|
||||
2.2. Text Representation of Addresses (rfc4291)</a>
|
||||
*/
|
||||
template<BOOST_URL_STRTOK_TPARAM>
|
||||
BOOST_URL_STRTOK_RETURN
|
||||
to_string(
|
||||
BOOST_URL_STRTOK_ARG(token)) const
|
||||
{
|
||||
to_string_impl(token);
|
||||
return token.result();
|
||||
}
|
||||
|
||||
/** Write a dotted decimal string representing the address to a buffer
|
||||
|
||||
The resulting buffer is not null-terminated.
|
||||
|
||||
@throw std::length_error `dest_size < ipv6_address::max_str_len`
|
||||
|
||||
@return The formatted string
|
||||
|
||||
@param dest The buffer in which to write,
|
||||
which must have at least `dest_size` space.
|
||||
|
||||
@param dest_size The size of the output buffer.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
core::string_view
|
||||
to_buffer(
|
||||
char* dest,
|
||||
std::size_t dest_size) const;
|
||||
|
||||
/** Return true if the address is unspecified
|
||||
|
||||
The address 0:0:0:0:0:0:0:0 is called the
|
||||
unspecified address. It indicates the
|
||||
absence of an address.
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.2">
|
||||
2.5.2. The Unspecified Address (rfc4291)</a>
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
bool
|
||||
is_unspecified() const noexcept;
|
||||
|
||||
/** Return true if the address is a loopback address
|
||||
|
||||
The unicast address 0:0:0:0:0:0:0:1 is called
|
||||
the loopback address. It may be used by a node
|
||||
to send an IPv6 packet to itself.
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.3">
|
||||
2.5.3. The Loopback Address (rfc4291)</a>
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
bool
|
||||
is_loopback() const noexcept;
|
||||
|
||||
/** Return true if the address is a mapped IPv4 address
|
||||
|
||||
This address type is used to represent the
|
||||
addresses of IPv4 nodes as IPv6 addresses.
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2">
|
||||
2.5.5.2. IPv4-Mapped IPv6 Address (rfc4291)</a>
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
bool
|
||||
is_v4_mapped() const noexcept;
|
||||
|
||||
/** Return true if two addresses are equal
|
||||
*/
|
||||
friend
|
||||
bool
|
||||
operator==(
|
||||
ipv6_address const& a1,
|
||||
ipv6_address const& a2) noexcept
|
||||
{
|
||||
return a1.addr_ == a2.addr_;
|
||||
}
|
||||
|
||||
/** Return true if two addresses are not equal
|
||||
*/
|
||||
friend
|
||||
bool
|
||||
operator!=(
|
||||
ipv6_address const& a1,
|
||||
ipv6_address const& a2) noexcept
|
||||
{
|
||||
return !( a1 == a2 );
|
||||
}
|
||||
|
||||
/** Return an address object that represents the loopback address
|
||||
|
||||
The unicast address 0:0:0:0:0:0:0:1 is called
|
||||
the loopback address. It may be used by a node
|
||||
to send an IPv6 packet to itself.
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.3">
|
||||
2.5.3. The Loopback Address (rfc4291)</a>
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
static
|
||||
ipv6_address
|
||||
loopback() noexcept;
|
||||
|
||||
// hidden friend
|
||||
friend
|
||||
std::ostream&
|
||||
operator<<(
|
||||
std::ostream& os,
|
||||
ipv6_address const& addr)
|
||||
{
|
||||
char buf[ipv6_address::max_str_len];
|
||||
auto const s = addr.to_buffer(
|
||||
buf, sizeof(buf));
|
||||
os << s;
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
BOOST_URL_DECL
|
||||
std::size_t
|
||||
print_impl(
|
||||
char* dest) const noexcept;
|
||||
|
||||
BOOST_URL_DECL
|
||||
void
|
||||
to_string_impl(
|
||||
string_token::arg& t) const;
|
||||
|
||||
bytes_type addr_{{}};
|
||||
};
|
||||
|
||||
/** Format the address to an output stream
|
||||
|
||||
This function writes the address to an
|
||||
output stream using standard notation.
|
||||
|
||||
@return The output stream, for chaining.
|
||||
|
||||
@param os The output stream to write to.
|
||||
|
||||
@param addr The address to write.
|
||||
*/
|
||||
std::ostream&
|
||||
operator<<(
|
||||
std::ostream& os,
|
||||
ipv6_address const& addr);
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Parse a string containing an IPv6 address.
|
||||
|
||||
This function attempts to parse the string
|
||||
as an IPv6 address and returns a result
|
||||
containing the address upon success, or
|
||||
an error code if the string does not contain
|
||||
a valid IPv6 address.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@return A result containing the address.
|
||||
|
||||
@param s The string to parse.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
system::result<ipv6_address>
|
||||
parse_ipv6_address(
|
||||
core::string_view s) noexcept;
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// Copyright (c) 2022 Vinnie Falco (vinnie.falco@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_OPTIONAL_HPP
|
||||
#define BOOST_URL_OPTIONAL_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
/** The type of optional used by the library
|
||||
|
||||
@note This alias is no longer supported and
|
||||
should not be used in new code. Please use
|
||||
`boost::optional` instead.
|
||||
|
||||
This alias is included for backwards
|
||||
compatibility with earlier versions of the
|
||||
library.
|
||||
|
||||
However, it will be removed in future releases,
|
||||
and using it in new code is not recommended.
|
||||
|
||||
Please use the updated version instead to
|
||||
ensure compatibility with future versions of
|
||||
the library.
|
||||
|
||||
*/
|
||||
#ifndef BOOST_URL_DOCS
|
||||
template<class T>
|
||||
using optional
|
||||
BOOST_URL_DEPRECATED("Use boost::optional<T> instead") =
|
||||
boost::optional<T>;
|
||||
#else
|
||||
template<class T>
|
||||
using optional = boost::optional<T>;
|
||||
#endif
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+934
@@ -0,0 +1,934 @@
|
||||
//
|
||||
// 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_PARAM_HPP
|
||||
#define BOOST_URL_PARAM_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/detail/optional_string.hpp>
|
||||
#include <boost/url/pct_string_view.hpp>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
struct param_pct_view;
|
||||
struct param_view;
|
||||
#endif
|
||||
|
||||
/** The type of no_value
|
||||
*/
|
||||
struct no_value_t
|
||||
{
|
||||
};
|
||||
|
||||
/** Constant indicating no value in a param
|
||||
*/
|
||||
constexpr no_value_t no_value{};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** A query parameter
|
||||
|
||||
Objects of this type represent a single key
|
||||
and value pair in a query string where a key
|
||||
is always present and may be empty, while the
|
||||
presence of a value is indicated by
|
||||
@ref has_value equal to true.
|
||||
An empty value is distinct from no value.
|
||||
|
||||
Depending on where the object was obtained,
|
||||
the strings may or may not contain percent
|
||||
escapes.
|
||||
|
||||
For most usages, key comparisons are
|
||||
case-sensitive and duplicate keys in
|
||||
a query are possible. However, it is
|
||||
the authority that has final control
|
||||
over how the query is interpreted.
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
query-params = query-param *( "&" query-param )
|
||||
query-param = key [ "=" value ]
|
||||
key = *qpchar
|
||||
value = *( qpchar / "=" )
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://en.wikipedia.org/wiki/Query_string"
|
||||
>Query string (Wikipedia)</a>
|
||||
|
||||
@see
|
||||
@ref param_view,
|
||||
@ref param_pct_view.
|
||||
*/
|
||||
struct param
|
||||
{
|
||||
/** The key
|
||||
|
||||
For most usages, key comparisons are
|
||||
case-sensitive and duplicate keys in
|
||||
a query are possible. However, it is
|
||||
the authority that has final control
|
||||
over how the query is interpreted.
|
||||
*/
|
||||
std::string key;
|
||||
|
||||
/** The value
|
||||
|
||||
The presence of a value is indicated by
|
||||
@ref has_value equal to true.
|
||||
An empty value is distinct from no value.
|
||||
*/
|
||||
std::string value;
|
||||
|
||||
/** True if a value is present
|
||||
|
||||
The presence of a value is indicated by
|
||||
`has_value == true`.
|
||||
An empty value is distinct from no value.
|
||||
*/
|
||||
bool has_value = false;
|
||||
|
||||
/** Constructor
|
||||
|
||||
Default constructed query parameters
|
||||
have an empty key and no value.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
param qp;
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->key == "" && this->value == "" && this->has_value == false
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
param() = default;
|
||||
|
||||
/** Constructor
|
||||
|
||||
Upon construction, this acquires
|
||||
ownership of the members of other
|
||||
via move construction. The moved
|
||||
from object is as if default
|
||||
constructed.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@par other The object to construct from.
|
||||
*/
|
||||
param(param&& other) noexcept
|
||||
: key(std::move(other.key))
|
||||
, value(std::move(other.value))
|
||||
, has_value(other.has_value)
|
||||
{
|
||||
#ifdef BOOST_URL_COW_STRINGS
|
||||
// for copy-on-write std::string
|
||||
other.key.clear();
|
||||
other.value.clear();
|
||||
#endif
|
||||
other.has_value = false;
|
||||
}
|
||||
|
||||
/** Constructor
|
||||
|
||||
Upon construction, this becomes a copy
|
||||
of `other`.
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->key == other.key && this->value == other.value && this->has_value == other.has_value
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `other.key.size() + other.value.size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Calls to allocate may throw.
|
||||
|
||||
@par other The object to construct from.
|
||||
*/
|
||||
param(param const& other) = default;
|
||||
|
||||
/** Assignment
|
||||
|
||||
Upon assignment, this acquires
|
||||
ownership of the members of other
|
||||
via move assignment. The moved
|
||||
from object is as if default
|
||||
constructed.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@par other The object to assign from.
|
||||
*/
|
||||
param&
|
||||
operator=(param&& other) noexcept
|
||||
{
|
||||
key = std::move(other.key);
|
||||
value = std::move(other.value);
|
||||
has_value = other.has_value;
|
||||
#ifdef BOOST_URL_COW_STRINGS
|
||||
// for copy-on-write std::string
|
||||
other.key.clear();
|
||||
other.value.clear();
|
||||
#endif
|
||||
other.has_value = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Assignment
|
||||
|
||||
Upon assignment, this becomes a copy
|
||||
of `other`.
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->key == other.key && this->value == other.value && this->has_value == other.has_value
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `other.key.size() + other.value.size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Calls to allocate may throw.
|
||||
|
||||
@par other The object to assign from.
|
||||
*/
|
||||
param& operator=(
|
||||
param const&) = default;
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs a parameter with a key
|
||||
and value.
|
||||
|
||||
No validation is performed on the strings.
|
||||
Ownership of the key and value is acquired
|
||||
by making copies.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
param qp( "key", "value" );
|
||||
@endcode
|
||||
|
||||
@code
|
||||
param qp( "key", optional<core::string_view>("value") );
|
||||
@endcode
|
||||
|
||||
@code
|
||||
param qp( "key", boost::none );
|
||||
@endcode
|
||||
|
||||
@code
|
||||
param qp( "key", nullptr );
|
||||
@endcode
|
||||
|
||||
@code
|
||||
param qp( "key", no_value );
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->key == key && this->value == value && this->has_value == true
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `key.size() + value.size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Calls to allocate may throw.
|
||||
|
||||
@tparam OptionalString An optional string
|
||||
type, such as `core::string_view`,
|
||||
`std::nullptr`, @ref no_value_t, or
|
||||
`optional<core::string_view>`.
|
||||
|
||||
@param key, value The key and value to set.
|
||||
*/
|
||||
template <class OptionalString>
|
||||
param(
|
||||
core::string_view key,
|
||||
OptionalString const& value)
|
||||
: param(key, detail::get_optional_string(value))
|
||||
{
|
||||
}
|
||||
|
||||
/** Assignment
|
||||
|
||||
The members of `other` are copied,
|
||||
re-using already existing string capacity.
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->key == other.key && this->value == other.value && this->has_value == other.has_value
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `other.key.size() + other.value.size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Calls to allocate may throw.
|
||||
|
||||
@param other The parameter to copy.
|
||||
*/
|
||||
param&
|
||||
operator=(param_view const& other);
|
||||
|
||||
/** Assignment
|
||||
|
||||
The members of `other` are copied,
|
||||
re-using already existing string capacity.
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->key == other.key && this->value == other.value && this->has_value == other.has_value
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `other.key.size() + other.value.size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Calls to allocate may throw.
|
||||
|
||||
@param other The parameter to copy.
|
||||
*/
|
||||
param&
|
||||
operator=(param_pct_view const& other);
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
// arrow support
|
||||
param const*
|
||||
operator->() const noexcept
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
// aggregate construction
|
||||
param(
|
||||
core::string_view key,
|
||||
core::string_view value,
|
||||
bool has_value) noexcept
|
||||
: key(key)
|
||||
, value(has_value
|
||||
? value
|
||||
: core::string_view())
|
||||
, has_value(has_value)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
param(
|
||||
core::string_view key,
|
||||
detail::optional_string const& value)
|
||||
: param(key, value.s, value.b)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** A query parameter
|
||||
|
||||
Objects of this type represent a single key
|
||||
and value pair in a query string where a key
|
||||
is always present and may be empty, while the
|
||||
presence of a value is indicated by
|
||||
@ref has_value equal to true.
|
||||
An empty value is distinct from no value.
|
||||
|
||||
Depending on where the object was obtained,
|
||||
the strings may or may not contain percent
|
||||
escapes.
|
||||
|
||||
For most usages, key comparisons are
|
||||
case-sensitive and duplicate keys in
|
||||
a query are possible. However, it is
|
||||
the authority that has final control
|
||||
over how the query is interpreted.
|
||||
|
||||
<br>
|
||||
|
||||
Keys and values in this object reference
|
||||
external character buffers.
|
||||
Ownership of the buffers is not transferred;
|
||||
the caller is responsible for ensuring that
|
||||
the assigned buffers remain valid until
|
||||
they are no longer referenced.
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
query-params = query-param *( "&" query-param )
|
||||
query-param = key [ "=" value ]
|
||||
key = *qpchar
|
||||
value = *( qpchar / "=" )
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://en.wikipedia.org/wiki/Query_string"
|
||||
>Query string (Wikipedia)</a>
|
||||
|
||||
@see
|
||||
@ref param,
|
||||
@ref param_pct_view.
|
||||
*/
|
||||
struct param_view
|
||||
{
|
||||
/** The key
|
||||
|
||||
For most usages, key comparisons are
|
||||
case-sensitive and duplicate keys in
|
||||
a query are possible. However, it is
|
||||
the authority that has final control
|
||||
over how the query is interpreted.
|
||||
*/
|
||||
core::string_view key;
|
||||
|
||||
/** The value
|
||||
|
||||
The presence of a value is indicated by
|
||||
@ref has_value equal to true.
|
||||
An empty value is distinct from no value.
|
||||
*/
|
||||
core::string_view value;
|
||||
|
||||
/** True if a value is present
|
||||
|
||||
The presence of a value is indicated by
|
||||
`has_value == true`.
|
||||
An empty value is distinct from no value.
|
||||
*/
|
||||
bool has_value = false;
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
/** Constructor
|
||||
|
||||
Default constructed query parameters
|
||||
have an empty key and no value.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
param_view qp;
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->key == "" && this->value == "" && this->has_value == false
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
param_view() = default;
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs a parameter with a key
|
||||
and value.
|
||||
No validation is performed on the strings.
|
||||
The new key and value reference
|
||||
the same corresponding underlying
|
||||
character buffers.
|
||||
Ownership of the buffers is not transferred;
|
||||
the caller is responsible for ensuring that
|
||||
the assigned buffers remain valid until
|
||||
they are no longer referenced.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
param_view qp( "key", "value" );
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->key.data() == key.data() && this->value.data() == value.data() && this->has_value == true
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@tparam OptionalString An optional string
|
||||
type, such as `core::string_view`,
|
||||
`std::nullptr`, @ref no_value_t, or
|
||||
`optional<core::string_view>`.
|
||||
|
||||
@param key, value The key and value to set.
|
||||
*/
|
||||
template <class OptionalString>
|
||||
param_view(
|
||||
core::string_view key,
|
||||
OptionalString const& value) noexcept
|
||||
: param_view(key, detail::get_optional_string(value))
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor
|
||||
|
||||
This function constructs a param
|
||||
which references the character buffers
|
||||
representing the key and value in another
|
||||
container.
|
||||
Ownership of the buffers is not transferred;
|
||||
the caller is responsible for ensuring that
|
||||
the assigned buffers remain valid until
|
||||
they are no longer referenced.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
param qp( "key", "value" );
|
||||
param_view qpv( qp );
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->key == key && this->value == value && this->has_value == other.has_value
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@param other The param to reference
|
||||
*/
|
||||
param_view(
|
||||
param const& other) noexcept
|
||||
: param_view(
|
||||
other.key,
|
||||
other.value,
|
||||
other.has_value)
|
||||
{
|
||||
}
|
||||
|
||||
/** Conversion
|
||||
|
||||
This function performs a conversion from
|
||||
a reference-like query parameter to one
|
||||
retaining ownership of the strings by
|
||||
making a copy.
|
||||
No validation is performed on the strings.
|
||||
|
||||
@par Complexity
|
||||
Linear in `this->key.size() + this->value.size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Calls to allocate may throw.
|
||||
*/
|
||||
explicit
|
||||
operator
|
||||
param()
|
||||
{
|
||||
return { key, value, has_value };
|
||||
}
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
// arrow support
|
||||
param_view const*
|
||||
operator->() const noexcept
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
// aggregate construction
|
||||
param_view(
|
||||
core::string_view key_,
|
||||
core::string_view value_,
|
||||
bool has_value_) noexcept
|
||||
: key(key_)
|
||||
, value(has_value_
|
||||
? value_
|
||||
: core::string_view())
|
||||
, has_value(has_value_)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
param_view(
|
||||
core::string_view key,
|
||||
detail::optional_string const& value)
|
||||
: param_view(key, value.s, value.b)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** A query parameter
|
||||
|
||||
Objects of this type represent a single key
|
||||
and value pair in a query string where a key
|
||||
is always present and may be empty, while the
|
||||
presence of a value is indicated by
|
||||
@ref has_value equal to true.
|
||||
An empty value is distinct from no value.
|
||||
|
||||
The strings may have percent escapes, and
|
||||
offer an additional invariant: they never
|
||||
contain an invalid percent-encoding.
|
||||
|
||||
For most usages, key comparisons are
|
||||
case-sensitive and duplicate keys in
|
||||
a query are possible. However, it is
|
||||
the authority that has final control
|
||||
over how the query is interpreted.
|
||||
|
||||
<br>
|
||||
|
||||
Keys and values in this object reference
|
||||
external character buffers.
|
||||
Ownership of the buffers is not transferred;
|
||||
the caller is responsible for ensuring that
|
||||
the assigned buffers remain valid until
|
||||
they are no longer referenced.
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
query-params = query-param *( "&" query-param )
|
||||
query-param = key [ "=" value ]
|
||||
key = *qpchar
|
||||
value = *( qpchar / "=" )
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://en.wikipedia.org/wiki/Query_string"
|
||||
>Query string (Wikipedia)</a>
|
||||
|
||||
@see
|
||||
@ref param,
|
||||
@ref param_view.
|
||||
*/
|
||||
struct param_pct_view
|
||||
{
|
||||
/** The key
|
||||
|
||||
For most usages, key comparisons are
|
||||
case-sensitive and duplicate keys in
|
||||
a query are possible. However, it is
|
||||
the authority that has final control
|
||||
over how the query is interpreted.
|
||||
*/
|
||||
pct_string_view key;
|
||||
|
||||
/** The value
|
||||
|
||||
The presence of a value is indicated by
|
||||
@ref has_value equal to true.
|
||||
An empty value is distinct from no value.
|
||||
*/
|
||||
pct_string_view value;
|
||||
|
||||
/** True if a value is present
|
||||
|
||||
The presence of a value is indicated by
|
||||
`has_value == true`.
|
||||
An empty value is distinct from no value.
|
||||
*/
|
||||
bool has_value = false;
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
/** Constructor
|
||||
|
||||
Default constructed query parameters
|
||||
have an empty key and no value.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
param_pct_view qp;
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->key == "" && this->value == "" && this->has_value == false
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
param_pct_view() = default;
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs a parameter with a key
|
||||
and value, which may both contain percent
|
||||
escapes.
|
||||
The new key and value reference
|
||||
the same corresponding underlying
|
||||
character buffers.
|
||||
Ownership of the buffers is not transferred;
|
||||
the caller is responsible for ensuring that
|
||||
the assigned buffers remain valid until
|
||||
they are no longer referenced.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
param_pct_view qp( "key", "value" );
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->key.data() == key.data() && this->value.data() == value.data() && this->has_value == true
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `key.size() + value.size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@throw system_error
|
||||
`key` or `value` contains an invalid percent-encoding.
|
||||
|
||||
@param key, value The key and value to set.
|
||||
*/
|
||||
param_pct_view(
|
||||
pct_string_view key,
|
||||
pct_string_view value) noexcept
|
||||
: key(key)
|
||||
, value(value)
|
||||
, has_value(true)
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs a parameter with a key
|
||||
and optional value, which may both
|
||||
contain percent escapes.
|
||||
|
||||
The new key and value reference
|
||||
the same corresponding underlying
|
||||
character buffers.
|
||||
|
||||
Ownership of the buffers is not transferred;
|
||||
the caller is responsible for ensuring that
|
||||
the assigned buffers remain valid until
|
||||
they are no longer referenced.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
param_pct_view qp( "key", optional<core::string_view>("value") );
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->key.data() == key.data() && this->value->data() == value->data() && this->has_value == true
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `key.size() + value->size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@throw system_error
|
||||
`key` or `value` contains an invalid percent-encoding.
|
||||
|
||||
@tparam OptionalString An optional
|
||||
`core::string_view` type, such as
|
||||
`boost::optional<core::string_view>` or
|
||||
`std::optional<core::string_view>`.
|
||||
|
||||
@param key, value The key and value to set.
|
||||
*/
|
||||
template <class OptionalString>
|
||||
param_pct_view(
|
||||
pct_string_view key,
|
||||
OptionalString const& value)
|
||||
: param_pct_view(key, detail::get_optional_string(value))
|
||||
{
|
||||
}
|
||||
|
||||
/** Construction
|
||||
|
||||
This converts a param which may
|
||||
contain unvalidated percent-escapes into
|
||||
a param whose key and value are
|
||||
guaranteed to contain strings with no
|
||||
invalid percent-escapes, otherwise
|
||||
an exception is thrown.
|
||||
|
||||
The new key and value reference
|
||||
the same corresponding underlying
|
||||
character buffers.
|
||||
Ownership of the buffers is not transferred;
|
||||
the caller is responsible for ensuring that
|
||||
the assigned buffers remain valid until
|
||||
they are no longer referenced.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
param_pct_view qp( param_view( "key", "value" ) );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `key.size() + value.size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@throw system_error
|
||||
`key` or `value` contains an invalid percent escape.
|
||||
|
||||
@param p The param to construct from.
|
||||
*/
|
||||
explicit
|
||||
param_pct_view(
|
||||
param_view const& p)
|
||||
: key(p.key)
|
||||
, value(p.has_value
|
||||
? pct_string_view(p.value)
|
||||
: pct_string_view())
|
||||
, has_value(p.has_value)
|
||||
{
|
||||
}
|
||||
|
||||
/** Conversion
|
||||
|
||||
This function performs a conversion from
|
||||
a reference-like query parameter to one
|
||||
retaining ownership of the strings by
|
||||
making a copy.
|
||||
|
||||
@par Complexity
|
||||
Linear in `this->key.size() + this->value.size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Calls to allocate may throw.
|
||||
*/
|
||||
explicit
|
||||
operator
|
||||
param() const
|
||||
{
|
||||
return param(
|
||||
static_cast<std::string>(key),
|
||||
static_cast<std::string>(value),
|
||||
has_value);
|
||||
}
|
||||
|
||||
operator
|
||||
param_view() const noexcept
|
||||
{
|
||||
return param_view(
|
||||
key, value, has_value);
|
||||
}
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
// arrow support
|
||||
param_pct_view const*
|
||||
operator->() const noexcept
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
// aggregate construction
|
||||
param_pct_view(
|
||||
pct_string_view key,
|
||||
pct_string_view value,
|
||||
bool has_value) noexcept
|
||||
: key(key)
|
||||
, value(has_value
|
||||
? value
|
||||
: pct_string_view())
|
||||
, has_value(has_value)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
param_pct_view(
|
||||
pct_string_view key,
|
||||
detail::optional_string const& value)
|
||||
: param_pct_view(key, value.s, value.b)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
inline
|
||||
param&
|
||||
param::
|
||||
operator=(
|
||||
param_view const& other)
|
||||
{
|
||||
// VFALCO operator= assignment
|
||||
// causes a loss of original capacity:
|
||||
// https://godbolt.org/z/nYef8445K
|
||||
//
|
||||
// key = other.key;
|
||||
// value = other.value;
|
||||
|
||||
// preserve capacity
|
||||
key.assign(
|
||||
other.key.data(),
|
||||
other.key.size());
|
||||
value.assign(
|
||||
other.value.data(),
|
||||
other.value.size());
|
||||
has_value = other.has_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline
|
||||
param&
|
||||
param::
|
||||
operator=(
|
||||
param_pct_view const& other)
|
||||
{
|
||||
// preserve capacity
|
||||
key.assign(
|
||||
other.key.data(),
|
||||
other.key.size());
|
||||
value.assign(
|
||||
other.value.data(),
|
||||
other.value.size());
|
||||
has_value = other.has_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+519
@@ -0,0 +1,519 @@
|
||||
//
|
||||
// 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
|
||||
+549
@@ -0,0 +1,549 @@
|
||||
//
|
||||
// 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_ENCODED_BASE_HPP
|
||||
#define BOOST_URL_PARAMS_ENCODED_BASE_HPP
|
||||
|
||||
#include <boost/url/detail/config.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_encoded_base
|
||||
{
|
||||
friend class url_view_base;
|
||||
friend class params_encoded_ref;
|
||||
friend class params_encoded_view;
|
||||
|
||||
detail::query_ref ref_;
|
||||
|
||||
params_encoded_base() = default;
|
||||
params_encoded_base(
|
||||
params_encoded_base const&) = default;
|
||||
params_encoded_base& operator=(
|
||||
params_encoded_base const&) = default;
|
||||
params_encoded_base(
|
||||
detail::query_ref const& ref) noexcept;
|
||||
|
||||
public:
|
||||
/** A Bidirectional iterator to a query parameter
|
||||
|
||||
Objects of this type allow iteration
|
||||
through the parameters in the query.
|
||||
Strings returned by iterators may
|
||||
contain percent escapes.
|
||||
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 refer to the underlying
|
||||
character buffer.
|
||||
Ownership is not transferred; the caller
|
||||
is responsible for ensuring that the
|
||||
lifetime of the buffer extends until
|
||||
it is no longer referenced by any
|
||||
container or iterator.
|
||||
*/
|
||||
#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_encoded_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_pct_view;
|
||||
|
||||
/// @copydoc reference
|
||||
using const_reference = param_pct_view;
|
||||
|
||||
/** 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 query corresponding to these params
|
||||
|
||||
This function returns the query string
|
||||
referenced by the container.
|
||||
The returned string may contain
|
||||
percent escapes.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( url_view( "?first=John&last=Doe" ).encoded_params().buffer() == "first=John&last=Doe" );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
query-params = query-param *( "&" query-param )
|
||||
query-param = key [ "=" value ]
|
||||
key = *qpchar
|
||||
value = *( qpchar / "=" )
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://en.wikipedia.org/wiki/Query_string"
|
||||
>Query string (Wikipedia)</a>
|
||||
*/
|
||||
pct_string_view
|
||||
buffer() const noexcept;
|
||||
|
||||
/** Return true if there are no params
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( ! url_view( "?key=value" ).encoded_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").encoded_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,
|
||||
which may contain percent escapes.
|
||||
The comparison is performed as if all
|
||||
escaped characters were decoded first.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( url_view( "?first=John&last=Doe" ).encoded_params().contains( "first" ) );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `this->buffer().size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@throw system_error
|
||||
`key` contains an invalid percent-encoding.
|
||||
|
||||
@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(
|
||||
pct_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,
|
||||
which may contain percent escapes.
|
||||
The comparison is performed as if all
|
||||
escaped characters were decoded first.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( url_view( "?first=John&last=Doe" ).encoded_params().count( "first" ) == 1 );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `this->buffer().size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@throw system_error
|
||||
`key` contains an invalid percent-encoding.
|
||||
|
||||
@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(
|
||||
pct_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,
|
||||
which may contain percent escapes.
|
||||
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" ).encoded_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()`.
|
||||
|
||||
@par Exception Safety
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@throw system_error
|
||||
`key` contains an invalid percent-encoding.
|
||||
|
||||
@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(
|
||||
pct_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, which may contain
|
||||
percent escapes.
|
||||
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.encoded_params().find( "first" ) != u.encoded_params().find( "first", ignore_case ) );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `this->buffer().size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@throw system_error
|
||||
`key` contains an invalid percent-encoding.
|
||||
|
||||
@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,
|
||||
pct_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, which may contain
|
||||
percent escapes.
|
||||
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" ).encoded_params().find_last( "last" )->value == "Doe" );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `this->buffer().size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@throw system_error
|
||||
`key` contains an invalid percent-encoding.
|
||||
|
||||
@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(
|
||||
pct_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, which may contain
|
||||
percent escapes.
|
||||
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.encoded_params().find_last( "last" ) != u.encoded_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,
|
||||
pct_string_view key,
|
||||
ignore_case_param ic = {}) const noexcept;
|
||||
|
||||
private:
|
||||
detail::params_iter_impl
|
||||
find_impl(
|
||||
detail::params_iter_impl,
|
||||
pct_string_view,
|
||||
ignore_case_param) const noexcept;
|
||||
|
||||
detail::params_iter_impl
|
||||
find_last_impl(
|
||||
detail::params_iter_impl,
|
||||
pct_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_encoded_base const& qp);
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#include <boost/url/impl/params_encoded_base.hpp>
|
||||
|
||||
#endif
|
||||
+1006
File diff suppressed because it is too large
Load Diff
+237
@@ -0,0 +1,237 @@
|
||||
//
|
||||
// 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_ENCODED_VIEW_HPP
|
||||
#define BOOST_URL_PARAMS_ENCODED_VIEW_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <boost/url/params_encoded_base.hpp>
|
||||
#include <boost/url/params_view.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <iosfwd>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
/** 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
|
||||
character buffer. The caller is responsible
|
||||
for ensuring that the lifetime of the buffer
|
||||
extends until it is no longer referenced.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
url_view u( "?first=John&last=Doe" );
|
||||
|
||||
params_encoded_view p = u.encoded_params();
|
||||
@endcode
|
||||
|
||||
Strings produced when elements are returned
|
||||
have type @ref param_pct_view and represent
|
||||
encoded strings. Strings passed to member
|
||||
functions may contain percent escapes, and
|
||||
throw exceptions on invalid inputs.
|
||||
|
||||
@par Iterator Invalidation
|
||||
Changes to the underlying character buffer
|
||||
can invalidate iterators which reference it.
|
||||
*/
|
||||
class BOOST_URL_DECL params_encoded_view
|
||||
: public params_encoded_base
|
||||
{
|
||||
friend class url_view_base;
|
||||
friend class params_view;
|
||||
friend class params_encoded_ref;
|
||||
friend struct query_rule_t;
|
||||
|
||||
params_encoded_view(
|
||||
detail::query_ref const& ref) noexcept;
|
||||
|
||||
public:
|
||||
/** Constructor
|
||||
|
||||
Default-constructed params have
|
||||
zero elements.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
params_encoded_view qp;
|
||||
@endcode
|
||||
|
||||
@par Effects
|
||||
@code
|
||||
return params_encoded_view( "" );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
params_encoded_view() = default;
|
||||
|
||||
/** Constructor
|
||||
|
||||
After construction both views
|
||||
reference the same character buffer.
|
||||
|
||||
Ownership is not transferred; the caller
|
||||
is responsible for ensuring the lifetime
|
||||
of the buffer extends until it is no
|
||||
longer referenced.
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->buffer().data() == other.buffer().data()
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing
|
||||
*/
|
||||
params_encoded_view(
|
||||
params_encoded_view const& other) = default;
|
||||
|
||||
/** Constructor
|
||||
|
||||
This function constructs params from
|
||||
a valid query parameter string, which
|
||||
can contain percent escapes. Unlike
|
||||
the parameters in URLs, the string
|
||||
passed here should not start with "?".
|
||||
Upon construction, the view
|
||||
references the character buffer pointed
|
||||
to by `s`. The caller is responsible
|
||||
for ensuring that the lifetime of the
|
||||
buffer extends until it is no longer
|
||||
referenced.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
params_encoded_view qp( "first=John&last=Doe" );
|
||||
@endcode
|
||||
|
||||
@par Effects
|
||||
@code
|
||||
return parse_query( s ).value();
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->buffer().data() == s.data()
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `s`.
|
||||
|
||||
@par Exception Safety
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@throw system_error
|
||||
`s` contains an invalid query parameter
|
||||
string.
|
||||
|
||||
@param s The string to parse.
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
query-params = [ query-param ] *( "&" query-param )
|
||||
|
||||
query-param = key [ "=" value ]
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
|
||||
>3.4. Query</a>
|
||||
*/
|
||||
params_encoded_view(
|
||||
core::string_view s);
|
||||
|
||||
/** Assignment
|
||||
|
||||
After assignment, both views
|
||||
reference the same underlying character
|
||||
buffer.
|
||||
|
||||
Ownership is not transferred; the caller
|
||||
is responsible for ensuring the lifetime
|
||||
of the buffer extends until it is no
|
||||
longer referenced.
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->buffer().data() == other.buffer().data()
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing
|
||||
*/
|
||||
params_encoded_view&
|
||||
operator=(
|
||||
params_encoded_view const&) = default;
|
||||
|
||||
/** Conversion
|
||||
|
||||
This conversion returns a new view which
|
||||
references the same underlying character
|
||||
buffer, and whose iterators and members
|
||||
return ordinary strings with decoding
|
||||
applied to any percent escapes.
|
||||
|
||||
Ownership is not transferred; the caller
|
||||
is responsible for ensuring the lifetime
|
||||
of the buffer extends until it is no
|
||||
longer referenced.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
params_view qp = parse_path( "/path/to/file.txt" ).value();
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
params_view( *this ).buffer().data() == this->buffer().data()
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing
|
||||
*/
|
||||
operator
|
||||
params_view() const noexcept;
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
friend
|
||||
BOOST_URL_DECL
|
||||
system::result<params_encoded_view>
|
||||
parse_query(core::string_view s) noexcept;
|
||||
};
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+967
@@ -0,0 +1,967 @@
|
||||
//
|
||||
// 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 <boost/url/detail/config.hpp>
|
||||
#include <boost/url/ignore_case.hpp>
|
||||
#include <boost/url/params_base.hpp>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
|
||||
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.
|
||||
|
||||
<br>
|
||||
|
||||
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:
|
||||
<br>
|
||||
|
||||
@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 BOOST_URL_DECL 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.
|
||||
|
||||
<br>
|
||||
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.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
|
||||
<br>
|
||||
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 <em>initializer-list</em>.
|
||||
|
||||
<br>
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
|
||||
<br>
|
||||
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<class FwdIt>
|
||||
void
|
||||
assign(FwdIt first, FwdIt last);
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
/** Append elements
|
||||
|
||||
This function appends a param to the view.
|
||||
|
||||
<br>
|
||||
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 <em>initializer-list</em> to the view.
|
||||
|
||||
<br>
|
||||
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.
|
||||
|
||||
<br>
|
||||
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<class FwdIt>
|
||||
iterator
|
||||
append(
|
||||
FwdIt first, FwdIt last);
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
/** Insert elements
|
||||
|
||||
This function inserts a param
|
||||
before the specified position.
|
||||
|
||||
<br>
|
||||
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.
|
||||
*/
|
||||
iterator
|
||||
insert(
|
||||
iterator before,
|
||||
param_view const& p);
|
||||
|
||||
/** Insert elements
|
||||
|
||||
This function inserts the params in
|
||||
an <em>initializer-list</em> before
|
||||
the specified position.
|
||||
|
||||
<br>
|
||||
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.
|
||||
*/
|
||||
iterator
|
||||
insert(
|
||||
iterator before,
|
||||
std::initializer_list<
|
||||
param_view> init);
|
||||
|
||||
/** Insert elements
|
||||
|
||||
This function inserts a range of
|
||||
params before the specified position.
|
||||
|
||||
<br>
|
||||
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<class FwdIt>
|
||||
iterator
|
||||
insert(
|
||||
iterator before,
|
||||
FwdIt first,
|
||||
FwdIt last);
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
/** Erase elements
|
||||
|
||||
This function removes an element from
|
||||
the container.
|
||||
|
||||
<br>
|
||||
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.
|
||||
|
||||
<br>
|
||||
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
|
||||
|
||||
<br>
|
||||
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.
|
||||
*/
|
||||
std::size_t
|
||||
erase(
|
||||
core::string_view key,
|
||||
ignore_case_param ic = {}) noexcept;
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
/** Replace elements
|
||||
|
||||
This function replaces the contents
|
||||
of the element at `pos` with the
|
||||
specified param.
|
||||
|
||||
<br>
|
||||
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.
|
||||
*/
|
||||
iterator
|
||||
replace(
|
||||
iterator pos,
|
||||
param_view const& p);
|
||||
|
||||
/** Replace elements
|
||||
|
||||
This function replaces a range of
|
||||
elements with the params in an
|
||||
<em>initializer-list</em>.
|
||||
|
||||
<br>
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
|
||||
<br>
|
||||
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<class FwdIt>
|
||||
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.
|
||||
|
||||
<br>
|
||||
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.
|
||||
*/
|
||||
iterator
|
||||
unset(
|
||||
iterator pos) noexcept;
|
||||
|
||||
/** Set a value
|
||||
|
||||
This function replaces the value of an
|
||||
element at the specified position.
|
||||
|
||||
<br>
|
||||
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.
|
||||
*/
|
||||
iterator
|
||||
set(
|
||||
iterator pos,
|
||||
core::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 }`.
|
||||
|
||||
<br>
|
||||
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.
|
||||
*/
|
||||
iterator
|
||||
set(
|
||||
core::string_view key,
|
||||
core::string_view value,
|
||||
ignore_case_param ic = {});
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
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;
|
||||
|
||||
template<class FwdIt>
|
||||
void
|
||||
assign(FwdIt first, FwdIt last,
|
||||
std::forward_iterator_tag);
|
||||
|
||||
// Doxygen cannot render ` = delete`
|
||||
template<class FwdIt>
|
||||
void
|
||||
assign(FwdIt first, FwdIt last,
|
||||
std::input_iterator_tag) = delete;
|
||||
|
||||
template<class FwdIt>
|
||||
iterator
|
||||
insert(
|
||||
iterator before,
|
||||
FwdIt first,
|
||||
FwdIt last,
|
||||
std::forward_iterator_tag);
|
||||
|
||||
// Doxygen cannot render ` = delete`
|
||||
template<class FwdIt>
|
||||
iterator
|
||||
insert(
|
||||
iterator before,
|
||||
FwdIt first,
|
||||
FwdIt last,
|
||||
std::input_iterator_tag) = delete;
|
||||
};
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
// This is in <boost/url/url_base.hpp>
|
||||
//
|
||||
// #include <boost/url/impl/params_ref.hpp>
|
||||
|
||||
#endif
|
||||
+286
@@ -0,0 +1,286 @@
|
||||
//
|
||||
// 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_VIEW_HPP
|
||||
#define BOOST_URL_PARAMS_VIEW_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/params_base.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
/** 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
|
||||
character buffer. The caller is responsible
|
||||
for ensuring that the lifetime of the buffer
|
||||
extends until it is no longer referenced.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
url_view u( "?first=John&last=Doe" );
|
||||
|
||||
params_view p = u.params();
|
||||
@endcode
|
||||
|
||||
Percent escapes in strings returned when
|
||||
dereferencing iterators are automatically
|
||||
decoded.
|
||||
|
||||
@par Iterator Invalidation
|
||||
Changes to the underlying character buffer
|
||||
can invalidate iterators which reference it.
|
||||
*/
|
||||
class params_view
|
||||
: public params_base
|
||||
{
|
||||
friend class url_view_base;
|
||||
friend class params_encoded_view;
|
||||
friend class params_ref;
|
||||
|
||||
params_view(
|
||||
detail::query_ref const& ref,
|
||||
encoding_opts opt) noexcept;
|
||||
|
||||
public:
|
||||
/** Constructor
|
||||
|
||||
Default-constructed params have
|
||||
zero elements.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
params_view qp;
|
||||
@endcode
|
||||
|
||||
@par Effects
|
||||
@code
|
||||
return params_view( "" );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
params_view() = default;
|
||||
|
||||
/** Constructor
|
||||
|
||||
After construction both views reference
|
||||
the same character buffer.
|
||||
|
||||
Ownership is not transferred; the caller
|
||||
is responsible for ensuring the lifetime
|
||||
of the buffer extends until it is no
|
||||
longer referenced.
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->buffer().data() == other.buffer().data()
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing
|
||||
*/
|
||||
params_view(
|
||||
params_view const& other) = default;
|
||||
|
||||
/** Constructor
|
||||
|
||||
After construction both views will
|
||||
reference the same character buffer
|
||||
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 buffer extends until it is no
|
||||
longer referenced.
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->buffer().data() == other.buffer().data()
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing
|
||||
*/
|
||||
params_view(
|
||||
params_view const& other,
|
||||
encoding_opts opt) noexcept;
|
||||
|
||||
/** Constructor
|
||||
|
||||
This function constructs params from
|
||||
a valid query parameter string, which
|
||||
can contain percent escapes. Unlike
|
||||
the parameters in URLs, the string
|
||||
passed here should not start with "?".
|
||||
Upon construction, the view references
|
||||
the character buffer pointed to by `s`.
|
||||
The caller is responsible for ensuring
|
||||
that the lifetime of the buffer extends
|
||||
until it is no longer referenced.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
params_view qp( "first=John&last=Doe" );
|
||||
@endcode
|
||||
|
||||
@par Effects
|
||||
@code
|
||||
return parse_query( s ).value();
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->buffer().data() == s.data()
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `s`.
|
||||
|
||||
@par Exception Safety
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@throw system_error
|
||||
`s` contains an invalid query parameter
|
||||
string.
|
||||
|
||||
@param s The string to parse.
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
query-params = [ query-param ] *( "&" query-param )
|
||||
|
||||
query-param = key [ "=" value ]
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
|
||||
>3.4. Query</a>
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
params_view(
|
||||
core::string_view s);
|
||||
|
||||
/** Constructor
|
||||
|
||||
This function constructs params from
|
||||
a valid query parameter string, which
|
||||
can contain percent escapes.
|
||||
|
||||
This instance will use the specified
|
||||
@ref encoding_opts when the values
|
||||
are decoded.
|
||||
|
||||
Unlike the parameters in URLs, the string
|
||||
passed here should not start with "?".
|
||||
Upon construction, the view will
|
||||
reference the character buffer pointed
|
||||
to by `s`. The caller is responsible
|
||||
for ensuring that the lifetime of the
|
||||
buffer extends until it is no longer
|
||||
referenced.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
encoding_opts opt;
|
||||
opt.space_as_plus = true;
|
||||
params_view qp( "name=John+Doe", opt );
|
||||
@endcode
|
||||
|
||||
@par Effects
|
||||
@code
|
||||
return params_view(parse_query( s ).value(), opt);
|
||||
@endcode
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->buffer().data() == s.data()
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `s`.
|
||||
|
||||
@par Exception Safety
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@throw system_error
|
||||
`s` contains an invalid query parameter
|
||||
string.
|
||||
|
||||
@param s The string to parse.
|
||||
|
||||
@param opt The options for decoding. If
|
||||
this parameter is omitted, `space_as_plus`
|
||||
is used.
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
query-params = [ query-param ] *( "&" query-param )
|
||||
|
||||
query-param = key [ "=" value ]
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
|
||||
>3.4. Query</a>
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
params_view(
|
||||
core::string_view s,
|
||||
encoding_opts opt);
|
||||
|
||||
/** Assignment
|
||||
|
||||
After assignment, both views reference
|
||||
the same underlying character buffer.
|
||||
|
||||
Ownership is not transferred; the caller
|
||||
is responsible for ensuring the lifetime
|
||||
of the buffer extends until it is no
|
||||
longer referenced.
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->buffer().data() == other.buffer().data()
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing
|
||||
*/
|
||||
params_view&
|
||||
operator=(
|
||||
params_view const&) = default;
|
||||
};
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+284
@@ -0,0 +1,284 @@
|
||||
//
|
||||
// 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_PARSE_HPP
|
||||
#define BOOST_URL_PARSE_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <boost/url/url_view.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
/** Return a reference to a parsed URL string
|
||||
|
||||
This function parses a string according
|
||||
to the grammar below and returns a view
|
||||
referencing the passed string upon success,
|
||||
else returns an error.
|
||||
Ownership of the string is not transferred;
|
||||
the caller is responsible for ensuring that
|
||||
the lifetime of the character buffer extends
|
||||
until the view is no longer being accessed.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
system::result< url_view > rv = parse_absolute_uri( "http://example.com/index.htm?id=1" );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
absolute-URI = scheme ":" hier-part [ "?" query ]
|
||||
|
||||
hier-part = "//" authority path-abempty
|
||||
/ path-absolute
|
||||
/ path-rootless
|
||||
/ path-empty
|
||||
@endcode
|
||||
|
||||
@throw std::length_error `s.size() > url_view::max_size`
|
||||
|
||||
@return A @ref result containing a value or an error
|
||||
|
||||
@param s The string to parse
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.3"
|
||||
>4.3. Absolute URI (rfc3986)</a>
|
||||
|
||||
@see
|
||||
@ref parse_origin_form,
|
||||
@ref parse_relative_ref,
|
||||
@ref parse_uri,
|
||||
@ref parse_uri_reference,
|
||||
@ref url_view.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
system::result<url_view>
|
||||
parse_absolute_uri(
|
||||
core::string_view s);
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Return a reference to a parsed URL string
|
||||
|
||||
This function parses a string according
|
||||
to the grammar below and returns a view
|
||||
referencing the passed string upon success,
|
||||
else returns an error.
|
||||
Ownership of the string is not transferred;
|
||||
the caller is responsible for ensuring that
|
||||
the lifetime of the character buffer extends
|
||||
until the view is no longer being accessed.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
system::result< url_view > = parse_origin_form( "/index.htm?layout=mobile" );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
origin-form = absolute-path [ "?" query ]
|
||||
|
||||
absolute-path = 1*( "/" segment )
|
||||
@endcode
|
||||
|
||||
@throw std::length_error `s.size() > url_view::max_size`
|
||||
|
||||
@return A @ref result containing a value or an error
|
||||
|
||||
@param s The string to parse
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.1"
|
||||
>5.3.1. origin-form (rfc7230)</a>
|
||||
|
||||
@see
|
||||
@ref parse_absolute_uri,
|
||||
@ref parse_relative_ref,
|
||||
@ref parse_uri,
|
||||
@ref parse_uri_reference,
|
||||
@ref url_view.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
system::result<url_view>
|
||||
parse_origin_form(
|
||||
core::string_view s);
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Return a reference to a parsed URL string
|
||||
|
||||
This function parses a string according
|
||||
to the grammar below and returns a view
|
||||
referencing the passed string upon success,
|
||||
else returns an error.
|
||||
Ownership of the string is not transferred;
|
||||
the caller is responsible for ensuring that
|
||||
the lifetime of the character buffer extends
|
||||
until the view is no longer being accessed.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
system::result< url_view > = parse_relative_ref( "images/dot.gif?v=hide#a" );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
relative-ref = relative-part [ "?" query ] [ "#" fragment ]
|
||||
|
||||
relative-part = "//" authority path-abempty
|
||||
/ path-absolute
|
||||
/ path-noscheme
|
||||
/ path-abempty
|
||||
/ path-empty
|
||||
@endcode
|
||||
|
||||
@return A @ref result containing a value or an error
|
||||
|
||||
@param s The string to parse
|
||||
|
||||
@throw std::length_error `s.size() > url_view::max_size`
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.2"
|
||||
>4.2. Relative Reference (rfc3986)</a>
|
||||
@li <a href="https://www.rfc-editor.org/errata/eid5428"
|
||||
>Errata ID: 5428 (rfc3986)</a>
|
||||
|
||||
@see
|
||||
@ref parse_absolute_uri,
|
||||
@ref parse_origin_form,
|
||||
@ref parse_uri,
|
||||
@ref parse_uri_reference,
|
||||
@ref url_view.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
system::result<url_view>
|
||||
parse_relative_ref(
|
||||
core::string_view s);
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Return a reference to a parsed URL string
|
||||
|
||||
This function parses a string according
|
||||
to the grammar below and returns a view
|
||||
referencing the passed string upon success,
|
||||
else returns an error.
|
||||
Ownership of the string is not transferred;
|
||||
the caller is responsible for ensuring that
|
||||
the lifetime of the character buffer extends
|
||||
until the view is no longer being accessed.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
system::result< url_view > = parse_uri( "https://www.example.com/index.htm?id=guest#s1" );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
|
||||
|
||||
hier-part = "//" authority path-abempty
|
||||
/ path-absolute
|
||||
/ path-rootless
|
||||
/ path-empty
|
||||
@endcode
|
||||
|
||||
@throw std::length_error `s.size() > url_view::max_size`
|
||||
|
||||
@return A @ref result containing a value or an error
|
||||
|
||||
@param s The string to parse
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3"
|
||||
>3. Syntax Components (rfc3986)</a>
|
||||
|
||||
@see
|
||||
@ref parse_absolute_uri,
|
||||
@ref parse_origin_form,
|
||||
@ref parse_relative_ref,
|
||||
@ref parse_uri_reference,
|
||||
@ref url_view.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
system::result<url_view>
|
||||
parse_uri(
|
||||
core::string_view s);
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Return a reference to a parsed URL string
|
||||
|
||||
This function parses a string according
|
||||
to the grammar below and returns a view
|
||||
referencing the passed string upon success,
|
||||
else returns an error.
|
||||
Ownership of the string is not transferred;
|
||||
the caller is responsible for ensuring that
|
||||
the lifetime of the character buffer extends
|
||||
until the view is no longer being accessed.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
system::result< url_view > = parse_uri_reference( "ws://echo.example.com/?name=boost#demo" );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
URI-reference = URI / relative-ref
|
||||
|
||||
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
|
||||
|
||||
relative-ref = relative-part [ "?" query ] [ "#" fragment ]
|
||||
|
||||
hier-part = "//" authority path-abempty
|
||||
/ path-absolute
|
||||
/ path-rootless
|
||||
/ path-empty
|
||||
|
||||
relative-part = "//" authority path-abempty
|
||||
/ path-absolute
|
||||
/ path-noscheme
|
||||
/ path-abempty
|
||||
/ path-empty
|
||||
@endcode
|
||||
|
||||
@throw std::length_error `s.size() > url_view::max_size`
|
||||
|
||||
@return A @ref result containing a value or an error
|
||||
|
||||
@param s The string to parse
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.1"
|
||||
>4.1. URI Reference (rfc3986)</a>
|
||||
@li <a href="https://www.rfc-editor.org/errata/eid5428"
|
||||
>Errata ID: 5428 (rfc3986)</a>
|
||||
|
||||
@see
|
||||
@ref parse_absolute_uri,
|
||||
@ref parse_origin_form,
|
||||
@ref parse_relative_ref,
|
||||
@ref parse_uri,
|
||||
@ref url_view.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
system::result<url_view>
|
||||
parse_uri_reference(
|
||||
core::string_view s);
|
||||
|
||||
} // url
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// 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_PARSE_PATH_HPP
|
||||
#define BOOST_URL_PARSE_PATH_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <boost/url/segments_encoded_view.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
/** Parse a string and return an encoded segment view
|
||||
|
||||
This function parses the string and returns the
|
||||
corresponding path object if the string is valid,
|
||||
otherwise returns an error.
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
path = [ "/" ] segment *( "/" segment )
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@return A valid view on success, otherwise an
|
||||
error code.
|
||||
|
||||
@param s The string to parse
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.3"
|
||||
>3.3. Path (rfc3986)</a>
|
||||
|
||||
@see
|
||||
@ref segments_encoded_view.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
system::result<segments_encoded_view>
|
||||
parse_path(core::string_view s) noexcept;
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// 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/CPPAlliance/url
|
||||
//
|
||||
|
||||
#ifndef BOOST_URL_PARSE_PARAMS_HPP
|
||||
#define BOOST_URL_PARSE_PARAMS_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <boost/url/params_encoded_view.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
/** Parse a string and return an encoded params view
|
||||
|
||||
This function parses the string and returns the
|
||||
corresponding params object if the string is valid,
|
||||
otherwise returns an error.
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@return A valid view on success, otherwise an
|
||||
error code.
|
||||
|
||||
@param s The string to parse
|
||||
|
||||
@par Specification
|
||||
|
||||
@see
|
||||
@ref params_encoded_view.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
system::result<params_encoded_view>
|
||||
parse_query(core::string_view s) noexcept;
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+462
@@ -0,0 +1,462 @@
|
||||
//
|
||||
// Copyright (c) 2022 Vinnie Falco (vinnie.falco@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_PCT_STRING_VIEW_HPP
|
||||
#define BOOST_URL_PCT_STRING_VIEW_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/encoding_opts.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/url/grammar/string_token.hpp>
|
||||
#include <boost/url/grammar/string_view_base.hpp>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
class decode_view;
|
||||
class pct_string_view;
|
||||
|
||||
pct_string_view
|
||||
make_pct_string_view_unsafe(
|
||||
char const*, std::size_t,
|
||||
std::size_t) noexcept;
|
||||
|
||||
namespace detail {
|
||||
core::string_view&
|
||||
ref(pct_string_view& s) noexcept;
|
||||
} // detail
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** A reference to a valid percent-encoded string
|
||||
|
||||
Objects of this type behave like a
|
||||
`core::string_view` and have the same interface,
|
||||
but offer an additional invariant: they can
|
||||
only be constructed from strings containing
|
||||
valid percent-escapes.
|
||||
|
||||
Attempting construction from a string
|
||||
containing invalid or malformed percent
|
||||
escapes results in an exception.
|
||||
|
||||
@par Operators
|
||||
The following operators are supported between
|
||||
@ref pct_string_view and any object that is
|
||||
convertible to `core::string_view`
|
||||
|
||||
@code
|
||||
bool operator==( pct_string_view, pct_string_view ) noexcept;
|
||||
bool operator!=( pct_string_view, pct_string_view ) noexcept;
|
||||
bool operator<=( pct_string_view, pct_string_view ) noexcept;
|
||||
bool operator< ( pct_string_view, pct_string_view ) noexcept;
|
||||
bool operator> ( pct_string_view, pct_string_view ) noexcept;
|
||||
bool operator>=( pct_string_view, pct_string_view ) noexcept;
|
||||
@endcode
|
||||
*/
|
||||
class pct_string_view final
|
||||
: public grammar::string_view_base
|
||||
{
|
||||
std::size_t dn_ = 0;
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
friend
|
||||
pct_string_view
|
||||
make_pct_string_view_unsafe(
|
||||
char const*, std::size_t,
|
||||
std::size_t) noexcept;
|
||||
|
||||
friend
|
||||
core::string_view&
|
||||
detail::ref(pct_string_view&) noexcept;
|
||||
#endif
|
||||
|
||||
// unsafe
|
||||
pct_string_view(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
std::size_t dn) noexcept
|
||||
: string_view_base(data, size)
|
||||
, dn_(dn)
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_URL_DECL
|
||||
void
|
||||
decode_impl(
|
||||
string_token::arg& dest,
|
||||
encoding_opts opt) const;
|
||||
|
||||
public:
|
||||
/** Constructor
|
||||
|
||||
Default constructed string are empty.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
constexpr pct_string_view() = default;
|
||||
|
||||
/** Constructor
|
||||
|
||||
The copy references the same
|
||||
underlying character buffer.
|
||||
Ownership is not transferred.
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->data() == other.data()
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@par other The string to copy.
|
||||
*/
|
||||
constexpr
|
||||
pct_string_view(
|
||||
pct_string_view const& other) = default;
|
||||
|
||||
/** Constructor
|
||||
|
||||
The newly constructed string references
|
||||
the specified character buffer.
|
||||
Ownership is not transferred.
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->data() == core::string_view(s).data()
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `core::string_view(s).size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@throw system_error
|
||||
The string contains an invalid percent encoding.
|
||||
|
||||
@tparam String A type convertible to `core::string_view`
|
||||
|
||||
@param s The string to construct from.
|
||||
*/
|
||||
template<
|
||||
class String
|
||||
#ifndef BOOST_URL_DOCS
|
||||
, class = typename std::enable_if<
|
||||
std::is_convertible<
|
||||
String,
|
||||
core::string_view
|
||||
>::value>::type
|
||||
#endif
|
||||
>
|
||||
pct_string_view(
|
||||
String const& s)
|
||||
: pct_string_view(
|
||||
detail::to_sv(s))
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor (deleted)
|
||||
*/
|
||||
pct_string_view(
|
||||
std::nullptr_t) = delete;
|
||||
|
||||
/** Constructor
|
||||
|
||||
The newly constructed string references
|
||||
the specified character buffer. Ownership
|
||||
is not transferred.
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->data() == s && this->size() == len
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `len`.
|
||||
|
||||
@par Exception Safety
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@throw system_error
|
||||
The string contains an invalid percent encoding.
|
||||
|
||||
@param s, len The string to construct from.
|
||||
*/
|
||||
pct_string_view(
|
||||
char const* s,
|
||||
std::size_t len)
|
||||
: pct_string_view(
|
||||
core::string_view(s, len))
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor
|
||||
|
||||
The newly constructed string references
|
||||
the specified character buffer. Ownership
|
||||
is not transferred.
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->data() == s.data() && this->size() == s.size()
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `s.size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@throw system_error
|
||||
The string contains an invalid percent encoding.
|
||||
|
||||
@param s The string to construct from.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
pct_string_view(
|
||||
core::string_view s);
|
||||
|
||||
/** Assignment
|
||||
|
||||
The copy references the same
|
||||
underlying character buffer.
|
||||
Ownership is not transferred.
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
this->data() == other.data()
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@par other The string to copy.
|
||||
*/
|
||||
pct_string_view& operator=(
|
||||
pct_string_view const& other) = default;
|
||||
|
||||
friend
|
||||
BOOST_URL_DECL
|
||||
system::result<pct_string_view>
|
||||
make_pct_string_view(
|
||||
core::string_view s) noexcept;
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
/** Return the decoded size
|
||||
|
||||
This function returns the number of
|
||||
characters in the resulting string if
|
||||
percent escapes were converted into
|
||||
ordinary characters.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
std::size_t
|
||||
decoded_size() const noexcept
|
||||
{
|
||||
return dn_;
|
||||
}
|
||||
|
||||
/** Return the string as a range of decoded characters
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@see
|
||||
@ref decode_view.
|
||||
*/
|
||||
decode_view
|
||||
operator*() const noexcept;
|
||||
|
||||
/** Return the string with percent-decoding
|
||||
|
||||
This function converts percent escapes
|
||||
in the string into ordinary characters
|
||||
and returns the result.
|
||||
When called with no arguments, the
|
||||
return type is `std::string`.
|
||||
Otherwise, the return type and style
|
||||
of output is determined by which string
|
||||
token is passed.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
assert( pct_string_view( "Program%20Files" ).decode() == "Program Files" );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `this->size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Calls to allocate may throw.
|
||||
String tokens may throw exceptions.
|
||||
|
||||
@param opt The options for encoding. If
|
||||
this parameter is omitted, the default
|
||||
options are used.
|
||||
|
||||
@param token An optional string token.
|
||||
If this parameter is omitted, then
|
||||
a new `std::string` is returned.
|
||||
Otherwise, the function return type
|
||||
is the result type of the token.
|
||||
|
||||
@see
|
||||
@ref encoding_opts,
|
||||
@ref string_token::return_string.
|
||||
*/
|
||||
template<BOOST_URL_STRTOK_TPARAM>
|
||||
BOOST_URL_STRTOK_RETURN
|
||||
decode(
|
||||
encoding_opts opt = {},
|
||||
BOOST_URL_STRTOK_ARG(token)) const
|
||||
{
|
||||
/* If you get a compile error here, it
|
||||
means that the token you passed does
|
||||
not meet the requirements stated
|
||||
in the documentation.
|
||||
*/
|
||||
static_assert(
|
||||
string_token::is_token<
|
||||
StringToken>::value,
|
||||
"Type requirements not met");
|
||||
|
||||
decode_impl(token, opt);
|
||||
return token.result();
|
||||
}
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
// arrow support
|
||||
pct_string_view const*
|
||||
operator->() const noexcept
|
||||
{
|
||||
return this;
|
||||
}
|
||||
#endif
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
// VFALCO No idea why this fails in msvc
|
||||
/** Swap
|
||||
*/
|
||||
/*BOOST_CXX14_CONSTEXPR*/ void swap(
|
||||
pct_string_view& s ) noexcept
|
||||
{
|
||||
string_view_base::swap(s);
|
||||
std::swap(dn_, s.dn_);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
namespace detail {
|
||||
// obtain modifiable reference to
|
||||
// underlying string, to handle
|
||||
// self-intersection on modifiers.
|
||||
inline
|
||||
core::string_view&
|
||||
ref(pct_string_view& s) noexcept
|
||||
{
|
||||
return s.s_;
|
||||
}
|
||||
|
||||
} // detail
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Return a valid percent-encoded string
|
||||
|
||||
If `s` is a valid percent-encoded string,
|
||||
the function returns the buffer as a valid
|
||||
view which may be used to perform decoding
|
||||
or measurements.
|
||||
Otherwise the result contains an error code.
|
||||
Upon success, the returned view references
|
||||
the original character buffer;
|
||||
Ownership is not transferred.
|
||||
|
||||
@par Complexity
|
||||
Linear in `s.size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@param s The string to validate.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
system::result<pct_string_view>
|
||||
make_pct_string_view(
|
||||
core::string_view s) noexcept;
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
// VFALCO semi-private for now
|
||||
inline
|
||||
pct_string_view
|
||||
make_pct_string_view_unsafe(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
std::size_t decoded_size) noexcept
|
||||
{
|
||||
#if 0
|
||||
BOOST_ASSERT(! make_pct_string_view(
|
||||
core::string_view(data, size)).has_error());
|
||||
#endif
|
||||
return pct_string_view(
|
||||
data, size, decoded_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
namespace detail {
|
||||
template <>
|
||||
inline
|
||||
core::string_view
|
||||
to_sv(pct_string_view const& s) noexcept
|
||||
{
|
||||
return s.substr();
|
||||
}
|
||||
} // detail
|
||||
#endif
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_RFC_ABSOLUTE_URI_RULE_HPP
|
||||
#define BOOST_URL_RFC_ABSOLUTE_URI_RULE_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
#include <boost/url/url_view.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
/** Rule for absolute-URI
|
||||
|
||||
@par Value Type
|
||||
@code
|
||||
using value_type = url_view;
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
Rules are used with the function @ref grammar::parse.
|
||||
@code
|
||||
system::result< url_view > rv = grammar::parse( "http://example.com/index.htm?id=1", absolute_uri_rule );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
absolute-URI = scheme ":" hier-part [ "?" query ]
|
||||
|
||||
hier-part = "//" authority path-abempty
|
||||
/ path-absolute
|
||||
/ path-rootless
|
||||
/ path-empty
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.3"
|
||||
>4.3. Absolute URI (rfc3986)</a>
|
||||
|
||||
@see
|
||||
@ref grammar::parse,
|
||||
@ref parse_absolute_uri,
|
||||
@ref url_view.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
constexpr __implementation_defined__ absolute_uri_rule;
|
||||
#else
|
||||
struct absolute_uri_rule_t
|
||||
{
|
||||
using value_type = url_view;
|
||||
|
||||
BOOST_URL_DECL
|
||||
auto
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end
|
||||
) const noexcept ->
|
||||
system::result<value_type>;
|
||||
};
|
||||
|
||||
constexpr absolute_uri_rule_t absolute_uri_rule{};
|
||||
#endif
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_RFC_AUTHORITY_RULE_HPP
|
||||
#define BOOST_URL_RFC_AUTHORITY_RULE_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/authority_view.hpp>
|
||||
#include <boost/url/error_types.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
/** Rule for authority
|
||||
|
||||
@par Value Type
|
||||
@code
|
||||
using value_type = authority_view;
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
Rules are used with the function @ref grammar::parse.
|
||||
@code
|
||||
system::result< authority_view > rv = grammar::parse( "user:pass@example.com:8080", authority_rule );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
authority = [ userinfo "@" ] host [ ":" port ]
|
||||
@endcode
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2"
|
||||
>3.2. Authority (rfc3986)</a>
|
||||
|
||||
@see
|
||||
@ref authority_view,
|
||||
@ref grammar::parse,
|
||||
@ref parse_authority.
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
constexpr __implementation_defined__ authority_rule;
|
||||
#else
|
||||
struct authority_rule_t
|
||||
{
|
||||
using value_type = authority_view;
|
||||
|
||||
BOOST_URL_DECL
|
||||
auto
|
||||
parse(
|
||||
char const*& it,
|
||||
char const* end
|
||||
) const noexcept ->
|
||||
system::result<value_type>;
|
||||
};
|
||||
|
||||
constexpr authority_rule_t authority_rule{};
|
||||
#endif
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
//
|
||||
// Copyright (c) 2022 alandefreitas (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_RFC_DETAIL_CHARSETS_HPP
|
||||
#define BOOST_URL_RFC_DETAIL_CHARSETS_HPP
|
||||
|
||||
#include <boost/url/rfc/pchars.hpp>
|
||||
#include <boost/url/rfc/sub_delim_chars.hpp>
|
||||
#include <boost/url/rfc/unreserved_chars.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
constexpr
|
||||
auto
|
||||
user_chars =
|
||||
unreserved_chars + sub_delim_chars;
|
||||
|
||||
constexpr
|
||||
auto
|
||||
password_chars =
|
||||
unreserved_chars + sub_delim_chars + ':';
|
||||
|
||||
constexpr
|
||||
auto
|
||||
userinfo_chars =
|
||||
password_chars;
|
||||
|
||||
constexpr
|
||||
auto
|
||||
host_chars =
|
||||
unreserved_chars + sub_delim_chars;
|
||||
|
||||
constexpr
|
||||
auto
|
||||
reg_name_chars =
|
||||
unreserved_chars + '-' + '.';
|
||||
|
||||
constexpr
|
||||
auto
|
||||
segment_chars =
|
||||
pchars;
|
||||
|
||||
constexpr
|
||||
auto
|
||||
path_chars =
|
||||
segment_chars + '/';
|
||||
|
||||
constexpr
|
||||
auto
|
||||
query_chars =
|
||||
pchars + '/' + '?';
|
||||
|
||||
constexpr
|
||||
auto
|
||||
param_key_chars = pchars
|
||||
+ '/' + '?' + '[' + ']'
|
||||
- '&' - '=';
|
||||
|
||||
constexpr
|
||||
auto
|
||||
param_value_chars = pchars
|
||||
+ '/' + '?'
|
||||
- '&';
|
||||
|
||||
constexpr
|
||||
auto
|
||||
fragment_chars =
|
||||
pchars + '/' + '?' + '#';
|
||||
|
||||
constexpr
|
||||
auto
|
||||
nocolon_pchars =
|
||||
pchars - ':';
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user