ext-boost/boost/url/detail/any_params_iter.hpp
2023-05-22 18:45:02 +10:00

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