File: //usr/include/boost/beast/core/impl/buffers_cat.ipp
//
// Copyright (c) 2016-2017 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_BEAST_IMPL_BUFFERS_CAT_IPP
#define BOOST_BEAST_IMPL_BUFFERS_CAT_IPP
#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/throw_exception.hpp>
#include <array>
#include <cstdint>
#include <iterator>
#include <new>
#include <stdexcept>
#include <tuple>
#include <utility>
namespace boost {
namespace beast {
template<class... Bn>
class buffers_cat_view<Bn...>::const_iterator
{
std::size_t n_;
std::tuple<Bn...> const* bn_;
std::array<char, detail::max_sizeof<
typename detail::buffer_sequence_iterator<Bn>::type...>()> buf_;
friend class buffers_cat_view<Bn...>;
template<std::size_t I>
using C = std::integral_constant<std::size_t, I>;
template<std::size_t I>
using iter_t = typename detail::buffer_sequence_iterator<
typename std::tuple_element<I, std::tuple<Bn...>>::type>::type;
template<std::size_t I>
iter_t<I>&
iter()
{
// type-pun
return *reinterpret_cast<
iter_t<I>*>(static_cast<void*>(buf_.data()));
}
template<std::size_t I>
iter_t<I> const&
iter() const
{
// type-pun
return *reinterpret_cast<
iter_t<I> const*>(static_cast<
void const*>(buf_.data()));
}
public:
using value_type = typename
detail::common_buffers_type<Bn...>::type;
using pointer = value_type const*;
using reference = value_type;
using difference_type = std::ptrdiff_t;
using iterator_category =
std::bidirectional_iterator_tag;
~const_iterator();
const_iterator();
const_iterator(const_iterator&& other);
const_iterator(const_iterator const& other);
const_iterator& operator=(const_iterator&& other);
const_iterator& operator=(const_iterator const& other);
bool
operator==(const_iterator const& other) const;
bool
operator!=(const_iterator const& other) const
{
return ! (*this == other);
}
reference
operator*() const;
pointer
operator->() const = delete;
const_iterator&
operator++();
const_iterator
operator++(int);
const_iterator&
operator--();
const_iterator
operator--(int);
private:
const_iterator(
std::tuple<Bn...> const& bn, bool at_end);
void
construct(C<sizeof...(Bn)> const&)
{
auto constexpr I = sizeof...(Bn);
n_ = I;
}
template<std::size_t I>
void
construct(C<I> const&)
{
if(boost::asio::buffer_size(
std::get<I>(*bn_)) != 0)
{
n_ = I;
new(&buf_[0]) iter_t<I>{
boost::asio::buffer_sequence_begin(
std::get<I>(*bn_))};
return;
}
construct(C<I+1>{});
}
void
rconstruct(C<0> const&)
{
auto constexpr I = 0;
if(boost::asio::buffer_size(
std::get<I>(*bn_)) != 0)
{
n_ = I;
new(&buf_[0]) iter_t<I>{
boost::asio::buffer_sequence_end(
std::get<I>(*bn_))};
return;
}
BOOST_THROW_EXCEPTION(std::logic_error{
"invalid iterator"});
}
template<std::size_t I>
void
rconstruct(C<I> const&)
{
if(boost::asio::buffer_size(
std::get<I>(*bn_)) != 0)
{
n_ = I;
new(&buf_[0]) iter_t<I>{
boost::asio::buffer_sequence_end(
std::get<I>(*bn_))};
return;
}
rconstruct(C<I-1>{});
}
void
destroy(C<sizeof...(Bn)> const&)
{
return;
}
template<std::size_t I>
void
destroy(C<I> const&)
{
if(n_ == I)
{
using Iter = iter_t<I>;
iter<I>().~Iter();
return;
}
destroy(C<I+1>{});
}
void
move(const_iterator&&,
C<sizeof...(Bn)> const&)
{
}
template<std::size_t I>
void
move(const_iterator&& other,
C<I> const&)
{
if(n_ == I)
{
new(&buf_[0]) iter_t<I>{
std::move(other.iter<I>())};
return;
}
move(std::move(other), C<I+1>{});
}
void
copy(const_iterator const&,
C<sizeof...(Bn)> const&)
{
}
template<std::size_t I>
void
copy(const_iterator const& other,
C<I> const&)
{
if(n_ == I)
{
new(&buf_[0]) iter_t<I>{
other.iter<I>()};
return;
}
copy(other, C<I+1>{});
}
bool
equal(const_iterator const&,
C<sizeof...(Bn)> const&) const
{
return true;
}
template<std::size_t I>
bool
equal(const_iterator const& other,
C<I> const&) const
{
if(n_ == I)
return iter<I>() == other.iter<I>();
return equal(other, C<I+1>{});
}
[[noreturn]]
reference
dereference(C<sizeof...(Bn)> const&) const
{
BOOST_THROW_EXCEPTION(std::logic_error{
"invalid iterator"});
}
template<std::size_t I>
reference
dereference(C<I> const&) const
{
if(n_ == I)
return *iter<I>();
return dereference(C<I+1>{});
}
[[noreturn]]
void
increment(C<sizeof...(Bn)> const&)
{
BOOST_THROW_EXCEPTION(std::logic_error{
"invalid iterator"});
}
template<std::size_t I>
void
increment(C<I> const&)
{
if(n_ == I)
{
if(++iter<I>() !=
boost::asio::buffer_sequence_end(
std::get<I>(*bn_)))
return;
using Iter = iter_t<I>;
iter<I>().~Iter();
return construct(C<I+1>{});
}
increment(C<I+1>{});
}
void
decrement(C<sizeof...(Bn)> const&)
{
auto constexpr I = sizeof...(Bn);
if(n_ == I)
rconstruct(C<I-1>{});
decrement(C<I-1>{});
}
template<std::size_t I>
void
decrement(C<I> const&)
{
if(n_ == I)
{
if(iter<I>() !=
boost::asio::buffer_sequence_begin(
std::get<I>(*bn_)))
{
--iter<I>();
return;
}
--n_;
using Iter = iter_t<I>;
iter<I>().~Iter();
rconstruct(C<I-1>{});
}
decrement(C<I-1>{});
}
void
decrement(C<0> const&)
{
auto constexpr I = 0;
if(iter<I>() !=
boost::asio::buffer_sequence_begin(
std::get<I>(*bn_)))
{
--iter<I>();
return;
}
BOOST_THROW_EXCEPTION(std::logic_error{
"invalid iterator"});
}
};
//------------------------------------------------------------------------------
template<class... Bn>
buffers_cat_view<Bn...>::
const_iterator::~const_iterator()
{
destroy(C<0>{});
}
template<class... Bn>
buffers_cat_view<Bn...>::
const_iterator::const_iterator()
: n_(sizeof...(Bn))
, bn_(nullptr)
{
}
template<class... Bn>
buffers_cat_view<Bn...>::
const_iterator::const_iterator(
std::tuple<Bn...> const& bn, bool at_end)
: bn_(&bn)
{
if(at_end)
n_ = sizeof...(Bn);
else
construct(C<0>{});
}
template<class... Bn>
buffers_cat_view<Bn...>::
const_iterator::const_iterator(const_iterator&& other)
: n_(other.n_)
, bn_(other.bn_)
{
move(std::move(other), C<0>{});
}
template<class... Bn>
buffers_cat_view<Bn...>::
const_iterator::const_iterator(const_iterator const& other)
: n_(other.n_)
, bn_(other.bn_)
{
copy(other, C<0>{});
}
template<class... Bn>
auto
buffers_cat_view<Bn...>::
const_iterator::operator=(const_iterator&& other) ->
const_iterator&
{
if(&other == this)
return *this;
destroy(C<0>{});
n_ = other.n_;
bn_ = other.bn_;
// VFALCO What about exceptions?
move(std::move(other), C<0>{});
return *this;
}
template<class... Bn>
auto
buffers_cat_view<Bn...>::
const_iterator::operator=(const_iterator const& other) ->
const_iterator&
{
if(&other == this)
return *this;
destroy(C<0>{});
n_ = other.n_;
bn_ = other.bn_;
// VFALCO What about exceptions?
copy(other, C<0>{});
return *this;
}
template<class... Bn>
bool
buffers_cat_view<Bn...>::
const_iterator::operator==(const_iterator const& other) const
{
if(bn_ != other.bn_)
return false;
if(n_ != other.n_)
return false;
return equal(other, C<0>{});
}
template<class... Bn>
auto
buffers_cat_view<Bn...>::
const_iterator::operator*() const ->
reference
{
return dereference(C<0>{});
}
template<class... Bn>
auto
buffers_cat_view<Bn...>::
const_iterator::operator++() ->
const_iterator&
{
increment(C<0>{});
return *this;
}
template<class... Bn>
auto
buffers_cat_view<Bn...>::
const_iterator::operator++(int) ->
const_iterator
{
auto temp = *this;
++(*this);
return temp;
}
template<class... Bn>
auto
buffers_cat_view<Bn...>::
const_iterator::operator--() ->
const_iterator&
{
decrement(C<sizeof...(Bn)>{});
return *this;
}
template<class... Bn>
auto
buffers_cat_view<Bn...>::
const_iterator::operator--(int) ->
const_iterator
{
auto temp = *this;
--(*this);
return temp;
}
//------------------------------------------------------------------------------
template<class... Bn>
buffers_cat_view<Bn...>::
buffers_cat_view(Bn const&... bn)
: bn_(bn...)
{
}
template<class... Bn>
inline
auto
buffers_cat_view<Bn...>::begin() const ->
const_iterator
{
return const_iterator{bn_, false};
}
template<class... Bn>
inline
auto
buffers_cat_view<Bn...>::end() const ->
const_iterator
{
return const_iterator{bn_, true};
}
} // beast
} // boost
#endif