429 lines
8.4 KiB
C++
429 lines
8.4 KiB
C++
//
|
|
// 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_,
|
|
string_view s0_ = {},
|
|
string_view s1_ = {}) noexcept
|
|
: s0(s0_)
|
|
, s1(s1_)
|
|
, empty(empty_)
|
|
{
|
|
}
|
|
|
|
public:
|
|
// these are adjusted
|
|
// when self-intersecting
|
|
string_view s0;
|
|
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(
|
|
string_view s,
|
|
bool ne = false) noexcept;
|
|
|
|
private:
|
|
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
|
|
{
|
|
BOOST_URL_DECL
|
|
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
|
|
{
|
|
BOOST_URL_DECL
|
|
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,
|
|
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
|