ext-boost/boost/url/impl/params_ref.ipp
2023-05-22 18:45:02 +10:00

282 lines
5.2 KiB
C++

//
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/url
//
#ifndef BOOST_URL_IMPL_PARAMS_REF_IPP
#define BOOST_URL_IMPL_PARAMS_REF_IPP
#include <boost/url/params_ref.hpp>
#include <boost/url/params_view.hpp>
#include <boost/url/url_base.hpp>
#include <boost/url/grammar/ci_string.hpp>
#include <boost/assert.hpp>
#include <utility>
namespace boost {
namespace urls {
//------------------------------------------------
//
// Special Members
//
//------------------------------------------------
auto
params_ref::
operator=(params_ref const& other) ->
params_ref&
{
if (!ref_.alias_of(other.ref_))
assign(other.begin(), other.end());
return *this;
}
params_ref::
operator
params_view() const noexcept
{
return { ref_, opt_ };
}
//------------------------------------------------
//
// Modifiers
//
//------------------------------------------------
void
params_ref::
assign(
std::initializer_list<
param_view> init)
{
assign(init.begin(), init.end());
}
auto
params_ref::
insert(
iterator before,
param_view const& p) ->
iterator
{
return iterator(
u_->edit_params(
before.it_,
before.it_,
detail::param_iter(p)),
opt_);
}
auto
params_ref::
insert(
iterator before,
std::initializer_list<
param_view> init) ->
iterator
{
return insert(
before,
init.begin(),
init.end());
}
std::size_t
params_ref::
erase(
string_view key,
ignore_case_param ic) noexcept
{
// end() can't be fully cached,
// since erase invalidates it.
iterator it;
{
auto const end_ = end();
it = find_last(end_, key, ic);
if(it == end_)
return 0;
}
std::size_t n = 0;
for(;;)
{
++n;
// Use it->key instead of key,
// to handle self-intersection
auto prev = find_last(it, (*it).key, ic);
if(prev == end())
break;
erase(it);
it = prev;
}
erase(it);
return n;
}
auto
params_ref::
replace(
iterator pos,
param_view const& p) ->
iterator
{
return iterator(
u_->edit_params(
pos.it_,
std::next(pos).it_,
detail::param_iter(p)),
opt_);
}
auto
params_ref::
replace(
iterator from,
iterator to,
std::initializer_list<
param_view> init) ->
iterator
{
return replace(
from,
to,
init.begin(),
init.end());
}
auto
params_ref::
unset(
iterator pos) noexcept ->
iterator
{
BOOST_ASSERT(pos.it_.nk > 0);
string_view s;
return iterator(
u_->edit_params(
pos.it_,
pos.it_.next(),
detail::param_value_iter(
pos.it_.nk - 1, s, false)),
opt_);
}
auto
params_ref::
set(
iterator pos,
string_view value) ->
iterator
{
BOOST_ASSERT(pos.it_.nk > 0);
return iterator(
u_->edit_params(
pos.it_,
pos.it_.next(),
detail::param_value_iter(
pos.it_.nk - 1, value, true)),
opt_);
}
auto
params_ref::
set(
string_view key,
string_view value,
ignore_case_param ic) ->
iterator
{
// VFALCO we can't cache end() here
// because it is invalidated
// every time we set or erase.
auto it0 = find(key, ic);
if(it0 == end())
return append({key, value});
it0 = set(it0, value);
auto it = end();
for(;;)
{
it = find_last(it, key, ic);
if(it == it0)
return it0;
it = erase(it);
}
}
//------------------------------------------------
//
// (implementation)
//
//------------------------------------------------
detail::params_iter_impl
params_ref::
find_impl(
detail::params_iter_impl it,
string_view key,
ignore_case_param ic) const noexcept
{
detail::params_iter_impl end_(u_->impl_, 0);
if(! ic)
{
for(;;)
{
if(it.equal(end_))
return it;
if(*it.key() == key)
return it;
it.increment();
}
}
for(;;)
{
if(it.equal(end_))
return it;
if( grammar::ci_is_equal(
*it.key(), key))
return it;
it.increment();
}
}
detail::params_iter_impl
params_ref::
find_last_impl(
detail::params_iter_impl it,
string_view key,
ignore_case_param ic) const noexcept
{
detail::params_iter_impl begin_(u_->impl_);
if(! ic)
{
for(;;)
{
if(it.equal(begin_))
return { u_->impl_, 0 };
it.decrement();
if(*it.key() == key)
return it;
}
}
for(;;)
{
if(it.equal(begin_))
return { u_->impl_, 0 };
it.decrement();
if(grammar::ci_is_equal(
*it.key(), key))
return it;
}
}
} // urls
} // boost
#endif