508 lines
9.1 KiB
C++
508 lines
9.1 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_IMPL_ANY_PARAMS_ITER_IPP
|
|
#define BOOST_URL_DETAIL_IMPL_ANY_PARAMS_ITER_IPP
|
|
|
|
#include <boost/url/detail/any_params_iter.hpp>
|
|
#include <boost/url/string_view.hpp>
|
|
#include <boost/url/rfc/detail/charsets.hpp>
|
|
|
|
namespace boost {
|
|
namespace urls {
|
|
namespace detail {
|
|
|
|
/*
|
|
When a string is transformed into a range of
|
|
params, the empty string becomes ambiguous:
|
|
it can be an empty range, or a range with
|
|
one param. The value `not_empty` is used on
|
|
construction to inform the transformation
|
|
that the empty string should be treated as
|
|
a one-element range. This simplifies
|
|
edit_params().
|
|
*/
|
|
|
|
//------------------------------------------------
|
|
//
|
|
// any_params_iter
|
|
//
|
|
//------------------------------------------------
|
|
|
|
any_params_iter::
|
|
~any_params_iter() noexcept = default;
|
|
|
|
//------------------------------------------------
|
|
//
|
|
// query_iter
|
|
//
|
|
//------------------------------------------------
|
|
|
|
query_iter::
|
|
query_iter(
|
|
string_view s,
|
|
bool ne) noexcept
|
|
: any_params_iter(
|
|
s.empty() && ! ne, s)
|
|
{
|
|
rewind();
|
|
}
|
|
|
|
void
|
|
query_iter::
|
|
rewind() noexcept
|
|
{
|
|
if(empty)
|
|
{
|
|
at_end_ = true;
|
|
return;
|
|
}
|
|
p_ = s0.begin();
|
|
if(! s0.empty())
|
|
{
|
|
auto pos =
|
|
s0.find_first_of('&');
|
|
if(pos != string_view::npos)
|
|
n_ = pos;
|
|
else
|
|
n_ = s0.size();
|
|
}
|
|
else
|
|
{
|
|
n_ = 0;
|
|
}
|
|
at_end_ = false;
|
|
}
|
|
|
|
bool
|
|
query_iter::
|
|
measure(
|
|
std::size_t& n) noexcept
|
|
{
|
|
if(at_end_)
|
|
return false;
|
|
// When interacting with the query as
|
|
// an intact string, we do not treat
|
|
// the plus sign as an encoded space.
|
|
encoding_opts opt;
|
|
opt.space_as_plus = false;
|
|
n += encoded_size(
|
|
string_view(p_, n_),
|
|
query_chars,
|
|
opt);
|
|
increment();
|
|
return true;
|
|
}
|
|
|
|
void
|
|
query_iter::
|
|
copy(
|
|
char*& dest,
|
|
char const* end) noexcept
|
|
{
|
|
BOOST_ASSERT(! at_end_);
|
|
// When interacting with the query as
|
|
// an intact string, we do not treat
|
|
// the plus sign as an encoded space.
|
|
encoding_opts opt;
|
|
opt.space_as_plus = false;
|
|
dest += encode_unsafe(
|
|
dest,
|
|
end - dest,
|
|
string_view(p_, n_),
|
|
query_chars,
|
|
opt);
|
|
increment();
|
|
}
|
|
|
|
void
|
|
query_iter::
|
|
increment() noexcept
|
|
{
|
|
p_ += n_;
|
|
if(p_ == s0.end())
|
|
{
|
|
at_end_ = true;
|
|
return;
|
|
}
|
|
++p_;
|
|
string_view s(p_, s0.end() - p_);
|
|
auto pos = s.find_first_of('&');
|
|
if(pos != string_view::npos)
|
|
n_ = pos;
|
|
else
|
|
n_ = s.size();
|
|
}
|
|
|
|
//------------------------------------------------
|
|
//
|
|
// param_iter
|
|
//
|
|
//------------------------------------------------
|
|
|
|
param_iter::
|
|
param_iter(
|
|
param_view const& p) noexcept
|
|
: any_params_iter(
|
|
false,
|
|
p.key,
|
|
p.value)
|
|
, has_value_(p.has_value)
|
|
{
|
|
}
|
|
|
|
void
|
|
param_iter::
|
|
rewind() noexcept
|
|
{
|
|
at_end_ = false;
|
|
}
|
|
|
|
bool
|
|
param_iter::
|
|
measure(std::size_t& n) noexcept
|
|
{
|
|
if(at_end_)
|
|
return false;
|
|
encoding_opts opt;
|
|
opt.space_as_plus = false;
|
|
n += encoded_size(
|
|
s0,
|
|
detail::param_key_chars,
|
|
opt);
|
|
if(has_value_)
|
|
{
|
|
++n; // '='
|
|
n += encoded_size(
|
|
s1,
|
|
detail::param_value_chars,
|
|
opt);
|
|
}
|
|
at_end_ = true;
|
|
return true;
|
|
}
|
|
|
|
void
|
|
param_iter::
|
|
copy(
|
|
char*& dest,
|
|
char const* end) noexcept
|
|
{
|
|
BOOST_ASSERT(! at_end_);
|
|
encoding_opts opt;
|
|
opt.space_as_plus = false;
|
|
dest += encode(
|
|
dest,
|
|
end - dest,
|
|
s0,
|
|
detail::param_key_chars,
|
|
opt);
|
|
if(has_value_)
|
|
{
|
|
*dest++ = '=';
|
|
dest += encode(
|
|
dest,
|
|
end - dest,
|
|
s1,
|
|
detail::param_value_chars,
|
|
opt);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------
|
|
//
|
|
// params_iter_base
|
|
//
|
|
//------------------------------------------------
|
|
|
|
void
|
|
params_iter_base::
|
|
measure_impl(
|
|
std::size_t& n,
|
|
param_view const& p) noexcept
|
|
{
|
|
encoding_opts opt;
|
|
opt.space_as_plus = false;
|
|
n += encoded_size(
|
|
p.key,
|
|
detail::param_key_chars,
|
|
opt);
|
|
if(p.has_value)
|
|
{
|
|
++n; // '='
|
|
n += encoded_size(
|
|
p.value,
|
|
detail::param_value_chars,
|
|
opt);
|
|
}
|
|
}
|
|
|
|
void
|
|
params_iter_base::
|
|
copy_impl(
|
|
char*& dest,
|
|
char const* end,
|
|
param_view const& p) noexcept
|
|
{
|
|
encoding_opts opt;
|
|
opt.space_as_plus = false;
|
|
dest += encode(
|
|
dest,
|
|
end - dest,
|
|
p.key,
|
|
detail::param_key_chars,
|
|
opt);
|
|
if(p.has_value)
|
|
{
|
|
*dest++ = '=';
|
|
dest += encode(
|
|
dest,
|
|
end - dest,
|
|
p.value,
|
|
detail::param_value_chars,
|
|
opt);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------
|
|
//
|
|
// param_encoded_iter
|
|
//
|
|
//------------------------------------------------
|
|
|
|
param_encoded_iter::
|
|
param_encoded_iter(
|
|
param_pct_view const& p) noexcept
|
|
: any_params_iter(
|
|
false,
|
|
p.key,
|
|
p.value)
|
|
, has_value_(p.has_value)
|
|
{
|
|
}
|
|
|
|
void
|
|
param_encoded_iter::
|
|
rewind() noexcept
|
|
{
|
|
at_end_ = false;
|
|
}
|
|
|
|
bool
|
|
param_encoded_iter::
|
|
measure(std::size_t& n) noexcept
|
|
{
|
|
if(at_end_)
|
|
return false;
|
|
encoding_opts opt;
|
|
opt.space_as_plus = false;
|
|
n += detail::re_encoded_size_unsafe(
|
|
s0,
|
|
detail::param_key_chars,
|
|
opt);
|
|
if(has_value_)
|
|
n += detail::re_encoded_size_unsafe(
|
|
s1,
|
|
detail::param_value_chars,
|
|
opt) + 1; // for '='
|
|
at_end_ = true;
|
|
return true;
|
|
}
|
|
|
|
void
|
|
param_encoded_iter::
|
|
copy(
|
|
char*& dest,
|
|
char const* end) noexcept
|
|
{
|
|
encoding_opts opt;
|
|
opt.space_as_plus = false;
|
|
detail::re_encode_unsafe(
|
|
dest,
|
|
end,
|
|
s0,
|
|
detail::param_key_chars,
|
|
opt);
|
|
if(has_value_)
|
|
{
|
|
*dest++ = '=';
|
|
detail::re_encode_unsafe(
|
|
dest,
|
|
end,
|
|
s1,
|
|
detail::param_value_chars,
|
|
opt);
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------
|
|
//
|
|
// params_encoded_iter_base
|
|
//
|
|
//------------------------------------------------
|
|
|
|
void
|
|
params_encoded_iter_base::
|
|
measure_impl(
|
|
std::size_t& n,
|
|
param_view const& p) noexcept
|
|
{
|
|
encoding_opts opt;
|
|
opt.space_as_plus = false;
|
|
n += detail::re_encoded_size_unsafe(
|
|
p.key,
|
|
detail::param_key_chars,
|
|
opt);
|
|
if(p.has_value)
|
|
n += detail::re_encoded_size_unsafe(
|
|
p.value,
|
|
detail::param_value_chars,
|
|
opt) + 1; // for '='
|
|
}
|
|
|
|
void
|
|
params_encoded_iter_base::
|
|
copy_impl(
|
|
char*& dest,
|
|
char const* end,
|
|
param_view const& p) noexcept
|
|
{
|
|
encoding_opts opt;
|
|
opt.space_as_plus = false;
|
|
detail::re_encode_unsafe(
|
|
dest,
|
|
end,
|
|
p.key,
|
|
detail::param_key_chars,
|
|
opt);
|
|
if(p.has_value)
|
|
{
|
|
*dest++ = '=';
|
|
detail::re_encode_unsafe(
|
|
dest,
|
|
end,
|
|
p.value,
|
|
detail::param_value_chars,
|
|
opt);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------
|
|
//
|
|
// param_value_iter
|
|
//
|
|
//------------------------------------------------
|
|
|
|
void
|
|
param_value_iter::
|
|
rewind() noexcept
|
|
{
|
|
at_end_ = false;
|
|
}
|
|
|
|
bool
|
|
param_value_iter::
|
|
measure(
|
|
std::size_t& n) noexcept
|
|
{
|
|
if(at_end_)
|
|
return false;
|
|
n += nk_; // skip key
|
|
if(has_value_)
|
|
{
|
|
encoding_opts opt;
|
|
opt.space_as_plus = false;
|
|
n += encoded_size(
|
|
s0,
|
|
detail::param_value_chars,
|
|
opt) + 1; // for '='
|
|
}
|
|
at_end_ = true;
|
|
return true;
|
|
}
|
|
|
|
void
|
|
param_value_iter::
|
|
copy(char*& it, char const* end) noexcept
|
|
{
|
|
it += nk_; // skip key
|
|
if(! has_value_)
|
|
return;
|
|
*it++ = '=';
|
|
encoding_opts opt;
|
|
opt.space_as_plus = false;
|
|
it += encode(
|
|
it,
|
|
end - it,
|
|
s0,
|
|
detail::param_value_chars,
|
|
opt);
|
|
}
|
|
|
|
//------------------------------------------------
|
|
//
|
|
// param_encoded_value_iter
|
|
//
|
|
//------------------------------------------------
|
|
|
|
void
|
|
param_encoded_value_iter::
|
|
rewind() noexcept
|
|
{
|
|
at_end_ = false;
|
|
}
|
|
|
|
bool
|
|
param_encoded_value_iter::
|
|
measure(
|
|
std::size_t& n) noexcept
|
|
{
|
|
if(at_end_)
|
|
return false;
|
|
n += nk_; // skip key
|
|
if(has_value_)
|
|
{
|
|
encoding_opts opt;
|
|
opt.space_as_plus = false;
|
|
n += detail::re_encoded_size_unsafe(
|
|
s0,
|
|
detail::param_value_chars,
|
|
opt) + 1; // for '='
|
|
}
|
|
at_end_ = true;
|
|
return true;
|
|
}
|
|
|
|
void
|
|
param_encoded_value_iter::
|
|
copy(
|
|
char*& dest,
|
|
char const* end) noexcept
|
|
{
|
|
dest += nk_; // skip key
|
|
if(! has_value_)
|
|
return;
|
|
*dest++ = '=';
|
|
encoding_opts opt;
|
|
opt.space_as_plus = false;
|
|
detail::re_encode_unsafe(
|
|
dest,
|
|
end,
|
|
s0,
|
|
detail::param_value_chars,
|
|
opt);
|
|
}
|
|
|
|
} // detail
|
|
} // urls
|
|
} // boost
|
|
|
|
#endif
|