mirror of
https://github.com/boostorg/beast.git
synced 2025-08-01 22:04:34 +02:00
Better buffer_cat:
buffer_cat now determines if all of the buffer sequences in the list of passed buffer sequences each have value types which are convertible to mutable_buffer. The returned concatenated sequence will be a MutableBufferSequence if all the passed buffer sequences meet the requirements of MutableBufferSequence, else the returned concatenated sequence will be a ConstBufferSequence.
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
* Use boost::lexical_cast instead of std::to_string
|
||||
* Fix prepare_buffers value_type
|
||||
* Fix consuming_buffers value_type
|
||||
* Better buffer_cat
|
||||
|
||||
HTTP
|
||||
|
||||
|
@@ -19,18 +19,21 @@
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** Concatenate 2 or more buffer sequences to form a `ConstBufferSequence`.
|
||||
/** Concatenate 2 or more buffer sequences.
|
||||
|
||||
This function returns a @b `ConstBufferSequence` that when iterated,
|
||||
efficiently concatenates the input buffer sequences. Copies of the
|
||||
arguments passed will be made; however, the returned object does
|
||||
not take ownership of the underlying memory. The application is still
|
||||
responsible for managing the lifetime of the referenced memory.
|
||||
This function returns a constant or mutable buffer sequence which,
|
||||
when iterated, efficiently concatenates the input buffer sequences.
|
||||
Copies of the arguments passed will be made; however, the returned
|
||||
object does not take ownership of the underlying memory. The application
|
||||
is still responsible for managing the lifetime of the referenced memory.
|
||||
|
||||
@param buffers The list of buffer sequences to concatenate.
|
||||
|
||||
@return A new @b `ConstBufferSequence` that represents the
|
||||
concatenation of the input buffer sequences.
|
||||
@return A new buffer sequence that represents the concatenation of
|
||||
the input buffer sequences. This buffer sequence will be a
|
||||
@b MutableBufferSequence if each of the passed buffer sequences is
|
||||
also a @b MutableBufferSequence, else the returned buffer sequence
|
||||
will be a @b ConstBufferSequence.
|
||||
*/
|
||||
#if GENERATING_DOCS
|
||||
template<class... BufferSequence>
|
||||
@@ -38,13 +41,14 @@ implementation_defined
|
||||
buffer_cat(BufferSequence const&... buffers)
|
||||
#else
|
||||
template<class B1, class B2, class... Bn>
|
||||
detail::buffer_cat_helper<
|
||||
boost::asio::const_buffer, B1, B2, Bn...>
|
||||
detail::buffer_cat_helper<B1, B2, Bn...>
|
||||
buffer_cat(B1 const& b1, B2 const& b2, Bn const&... bn)
|
||||
#endif
|
||||
{
|
||||
static_assert(
|
||||
detail::is_all_ConstBufferSequence<B1, B2, Bn...>::value,
|
||||
"BufferSequence requirements not met");
|
||||
return detail::buffer_cat_helper<
|
||||
boost::asio::const_buffer,
|
||||
B1, B2, Bn...>{b1, b2, bn...};
|
||||
}
|
||||
|
||||
|
@@ -8,6 +8,8 @@
|
||||
#ifndef BEAST_DETAIL_BUFFER_CAT_HPP
|
||||
#define BEAST_DETAIL_BUFFER_CAT_HPP
|
||||
|
||||
#include <beast/core/buffer_concepts.hpp>
|
||||
#include <beast/core/detail/type_traits.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
@@ -19,24 +21,36 @@
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
template<class... Bn>
|
||||
struct common_buffers_type
|
||||
{
|
||||
using type = typename std::conditional<
|
||||
std::is_convertible<std::tuple<Bn...>,
|
||||
typename repeat_tuple<sizeof...(Bn),
|
||||
boost::asio::mutable_buffer>::type>::value,
|
||||
boost::asio::mutable_buffer,
|
||||
boost::asio::const_buffer>::type;
|
||||
};
|
||||
|
||||
template<class... Bn>
|
||||
class buffer_cat_helper
|
||||
{
|
||||
std::tuple<Bs...> bs_;
|
||||
std::tuple<Bn...> bn_;
|
||||
|
||||
public:
|
||||
using value_type = ValueType;
|
||||
using value_type = typename
|
||||
common_buffers_type<Bn...>::type;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
buffer_cat_helper(buffer_cat_helper&&) = default;
|
||||
buffer_cat_helper(buffer_cat_helper const&) = default;
|
||||
buffer_cat_helper& operator=(buffer_cat_helper&&) = default;
|
||||
buffer_cat_helper& operator=(buffer_cat_helper const&) = default;
|
||||
buffer_cat_helper& operator=(buffer_cat_helper&&) = delete;
|
||||
buffer_cat_helper& operator=(buffer_cat_helper const&) = delete;
|
||||
|
||||
explicit
|
||||
buffer_cat_helper(Bs const&... bs)
|
||||
: bs_(bs...)
|
||||
buffer_cat_helper(Bn const&... bn)
|
||||
: bn_(bn...)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -47,39 +61,22 @@ public:
|
||||
end() const;
|
||||
};
|
||||
|
||||
template<class U>
|
||||
std::size_t constexpr
|
||||
max_sizeof()
|
||||
{
|
||||
return sizeof(U);
|
||||
}
|
||||
|
||||
template<class U0, class U1, class... Us>
|
||||
std::size_t constexpr
|
||||
max_sizeof()
|
||||
{
|
||||
return
|
||||
max_sizeof<U0>() > max_sizeof<U1, Us...>() ?
|
||||
max_sizeof<U0>() : max_sizeof<U1, Us...>();
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
class buffer_cat_helper<
|
||||
ValueType, Bs...>::const_iterator
|
||||
template<class... Bn>
|
||||
class buffer_cat_helper<Bn...>::const_iterator
|
||||
{
|
||||
std::size_t n_;
|
||||
std::tuple<Bs...> const* bs_;
|
||||
std::tuple<Bn...> const* bn_;
|
||||
std::array<std::uint8_t,
|
||||
max_sizeof<typename Bs::const_iterator...>()> buf_;
|
||||
max_sizeof<typename Bn::const_iterator...>()> buf_;
|
||||
|
||||
friend class buffer_cat_helper<ValueType, Bs...>;
|
||||
friend class buffer_cat_helper<Bn...>;
|
||||
|
||||
template<std::size_t I>
|
||||
using C = std::integral_constant<std::size_t, I>;
|
||||
|
||||
template<std::size_t I>
|
||||
using iter_t = typename std::tuple_element<
|
||||
I, std::tuple<Bs...>>::type::const_iterator;
|
||||
I, std::tuple<Bn...>>::type::const_iterator;
|
||||
|
||||
template<std::size_t I>
|
||||
iter_t<I>&
|
||||
@@ -98,7 +95,8 @@ class buffer_cat_helper<
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type = ValueType;
|
||||
using value_type = typename
|
||||
common_buffers_type<Bn...>::type;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
@@ -151,39 +149,39 @@ public:
|
||||
|
||||
private:
|
||||
const_iterator(
|
||||
std::tuple<Bs...> const& bs, bool at_end);
|
||||
std::tuple<Bn...> const& bn, bool at_end);
|
||||
|
||||
void
|
||||
construct(C<sizeof...(Bs)>)
|
||||
construct(C<sizeof...(Bn)> const&)
|
||||
{
|
||||
auto constexpr I = sizeof...(Bs);
|
||||
auto constexpr I = sizeof...(Bn);
|
||||
n_ = I;
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
void
|
||||
construct(C<I>)
|
||||
construct(C<I> const&)
|
||||
{
|
||||
if(std::get<I>(*bs_).begin() !=
|
||||
std::get<I>(*bs_).end())
|
||||
if(std::get<I>(*bn_).begin() !=
|
||||
std::get<I>(*bn_).end())
|
||||
{
|
||||
n_ = I;
|
||||
new(buf_.data()) iter_t<I>{
|
||||
std::get<I>(*bs_).begin()};
|
||||
std::get<I>(*bn_).begin()};
|
||||
return;
|
||||
}
|
||||
construct(C<I+1>{});
|
||||
}
|
||||
|
||||
void
|
||||
destroy(C<sizeof...(Bs)>)
|
||||
destroy(C<sizeof...(Bn)> const&)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
void
|
||||
destroy(C<I>)
|
||||
destroy(C<I> const&)
|
||||
{
|
||||
if(n_ == I)
|
||||
{
|
||||
@@ -195,13 +193,15 @@ private:
|
||||
}
|
||||
|
||||
void
|
||||
move(C<sizeof...(Bs)>, const_iterator&&)
|
||||
move(const_iterator&&,
|
||||
C<sizeof...(Bn)> const&)
|
||||
{
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
void
|
||||
move(C<I>, const_iterator&& other)
|
||||
move(const_iterator&& other,
|
||||
C<I> const&)
|
||||
{
|
||||
if(n_ == I)
|
||||
{
|
||||
@@ -209,17 +209,19 @@ private:
|
||||
std::move(other.iter<I>())};
|
||||
return;
|
||||
}
|
||||
move(C<I+1>{}, std::move(other));
|
||||
move(std::move(other), C<I+1>{});
|
||||
}
|
||||
|
||||
void
|
||||
copy(C<sizeof...(Bs)>, const_iterator const&)
|
||||
copy(const_iterator const&,
|
||||
C<sizeof...(Bn)> const&)
|
||||
{
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
void
|
||||
copy(C<I>, const_iterator const& other)
|
||||
copy(const_iterator const& other,
|
||||
C<I> const&)
|
||||
{
|
||||
if(n_ == I)
|
||||
{
|
||||
@@ -227,35 +229,36 @@ private:
|
||||
other.iter<I>()};
|
||||
return;
|
||||
}
|
||||
copy(C<I+1>{}, other);
|
||||
copy(other, C<I+1>{});
|
||||
}
|
||||
|
||||
bool
|
||||
equal(C<sizeof...(Bs)>,
|
||||
const_iterator const&) const
|
||||
equal(const_iterator const&,
|
||||
C<sizeof...(Bn)> const&) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
bool
|
||||
equal(C<I>, const_iterator const& other) const
|
||||
equal(const_iterator const& other,
|
||||
C<I> const&) const
|
||||
{
|
||||
if(n_ == I)
|
||||
return iter<I>() == other.iter<I>();
|
||||
return equal(C<I+1>{}, other);
|
||||
return equal(other, C<I+1>{});
|
||||
}
|
||||
|
||||
[[noreturn]]
|
||||
reference
|
||||
dereference(C<sizeof...(Bs)>) const
|
||||
dereference(C<sizeof...(Bn)> const&) const
|
||||
{
|
||||
throw std::logic_error("invalid iterator");
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
reference
|
||||
dereference(C<I>) const
|
||||
dereference(C<I> const&) const
|
||||
{
|
||||
if(n_ == I)
|
||||
return *iter<I>();
|
||||
@@ -264,19 +267,19 @@ private:
|
||||
|
||||
[[noreturn]]
|
||||
void
|
||||
increment(C<sizeof...(Bs)>)
|
||||
increment(C<sizeof...(Bn)> const&)
|
||||
{
|
||||
throw std::logic_error("invalid iterator");
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
void
|
||||
increment(C<I>)
|
||||
increment(C<I> const&)
|
||||
{
|
||||
if(n_ == I)
|
||||
{
|
||||
if(++iter<I>() !=
|
||||
std::get<I>(*bs_).end())
|
||||
std::get<I>(*bn_).end())
|
||||
return;
|
||||
using Iter = iter_t<I>;
|
||||
iter<I>().~Iter();
|
||||
@@ -286,23 +289,23 @@ private:
|
||||
}
|
||||
|
||||
void
|
||||
decrement(C<sizeof...(Bs)>)
|
||||
decrement(C<sizeof...(Bn)> const&)
|
||||
{
|
||||
auto constexpr I = sizeof...(Bs);
|
||||
auto constexpr I = sizeof...(Bn);
|
||||
if(n_ == I)
|
||||
{
|
||||
--n_;
|
||||
new(buf_.data()) iter_t<I-1>{
|
||||
std::get<I-1>(*bs_).end()};
|
||||
std::get<I-1>(*bn_).end()};
|
||||
}
|
||||
decrement(C<I-1>{});
|
||||
}
|
||||
|
||||
void
|
||||
decrement(C<0>)
|
||||
decrement(C<0> const&)
|
||||
{
|
||||
auto constexpr I = 0;
|
||||
if(iter<I>() != std::get<I>(*bs_).begin())
|
||||
if(iter<I>() != std::get<I>(*bn_).begin())
|
||||
{
|
||||
--iter<I>();
|
||||
return;
|
||||
@@ -312,11 +315,11 @@ private:
|
||||
|
||||
template<std::size_t I>
|
||||
void
|
||||
decrement(C<I>)
|
||||
decrement(C<I> const&)
|
||||
{
|
||||
if(n_ == I)
|
||||
{
|
||||
if(iter<I>() != std::get<I>(*bs_).begin())
|
||||
if(iter<I>() != std::get<I>(*bn_).begin())
|
||||
{
|
||||
--iter<I>();
|
||||
return;
|
||||
@@ -325,7 +328,7 @@ private:
|
||||
using Iter = iter_t<I>;
|
||||
iter<I>().~Iter();
|
||||
new(buf_.data()) iter_t<I-1>{
|
||||
std::get<I-1>(*bs_).end()};
|
||||
std::get<I-1>(*bn_).end()};
|
||||
}
|
||||
decrement(C<I-1>{});
|
||||
}
|
||||
@@ -333,54 +336,54 @@ private:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
template<class... Bn>
|
||||
buffer_cat_helper<Bn...>::
|
||||
const_iterator::~const_iterator()
|
||||
{
|
||||
destroy(C<0>{});
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
template<class... Bn>
|
||||
buffer_cat_helper<Bn...>::
|
||||
const_iterator::const_iterator()
|
||||
: n_(sizeof...(Bs))
|
||||
, bs_(nullptr)
|
||||
: n_(sizeof...(Bn))
|
||||
, bn_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
template<class... Bn>
|
||||
buffer_cat_helper<Bn...>::
|
||||
const_iterator::const_iterator(
|
||||
std::tuple<Bs...> const& bs, bool at_end)
|
||||
: bs_(&bs)
|
||||
std::tuple<Bn...> const& bn, bool at_end)
|
||||
: bn_(&bn)
|
||||
{
|
||||
if(at_end)
|
||||
n_ = sizeof...(Bs);
|
||||
n_ = sizeof...(Bn);
|
||||
else
|
||||
construct(C<0>{});
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
template<class... Bn>
|
||||
buffer_cat_helper<Bn...>::
|
||||
const_iterator::const_iterator(const_iterator&& other)
|
||||
: n_(other.n_)
|
||||
, bs_(other.bs_)
|
||||
, bn_(other.bn_)
|
||||
{
|
||||
move(C<0>{}, std::move(other));
|
||||
move(std::move(other), C<0>{});
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
template<class... Bn>
|
||||
buffer_cat_helper<Bn...>::
|
||||
const_iterator::const_iterator(const_iterator const& other)
|
||||
: n_(other.n_)
|
||||
, bs_(other.bs_)
|
||||
, bn_(other.bn_)
|
||||
{
|
||||
copy(C<0>{}, other);
|
||||
copy(other, C<0>{});
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
template<class... Bn>
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
buffer_cat_helper<Bn...>::
|
||||
const_iterator::operator=(const_iterator&& other) ->
|
||||
const_iterator&
|
||||
{
|
||||
@@ -388,14 +391,14 @@ const_iterator::operator=(const_iterator&& other) ->
|
||||
return *this;
|
||||
destroy(C<0>{});
|
||||
n_ = other.n_;
|
||||
bs_ = other.bs_;
|
||||
move(C<0>{}, std::move(other));
|
||||
bn_ = other.bn_;
|
||||
move(std::move(other), C<0>{});
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
template<class... Bn>
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
buffer_cat_helper<Bn...>::
|
||||
const_iterator::operator=(const_iterator const& other) ->
|
||||
const_iterator&
|
||||
{
|
||||
@@ -403,35 +406,35 @@ const_iterator&
|
||||
return *this;
|
||||
destroy(C<0>{});
|
||||
n_ = other.n_;
|
||||
bs_ = other.bs_;
|
||||
copy(C<0>{}, other);
|
||||
bn_ = other.bn_;
|
||||
copy(other, C<0>{});
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
template<class... Bn>
|
||||
bool
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
buffer_cat_helper<Bn...>::
|
||||
const_iterator::operator==(const_iterator const& other) const
|
||||
{
|
||||
if(bs_ != other.bs_)
|
||||
if(bn_ != other.bn_)
|
||||
return false;
|
||||
if(n_ != other.n_)
|
||||
return false;
|
||||
return equal(C<0>{}, other);
|
||||
return equal(other, C<0>{});
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
template<class... Bn>
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
buffer_cat_helper<Bn...>::
|
||||
const_iterator::operator*() const ->
|
||||
reference
|
||||
{
|
||||
return dereference(C<0>{});
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
template<class... Bn>
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
buffer_cat_helper<Bn...>::
|
||||
const_iterator::operator++() ->
|
||||
const_iterator&
|
||||
{
|
||||
@@ -439,30 +442,32 @@ const_iterator::operator++() ->
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
template<class... Bn>
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
buffer_cat_helper<Bn...>::
|
||||
const_iterator::operator--() ->
|
||||
const_iterator&
|
||||
{
|
||||
decrement(C<sizeof...(Bs)>{});
|
||||
decrement(C<sizeof...(Bn)>{});
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
template<class... Bn>
|
||||
inline
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::begin() const ->
|
||||
buffer_cat_helper<Bn...>::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator(bs_, false);
|
||||
return const_iterator{bn_, false};
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
template<class... Bn>
|
||||
inline
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::end() const ->
|
||||
buffer_cat_helper<Bn...>::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator(bs_, true);
|
||||
return const_iterator{bn_, true};
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
@@ -85,6 +85,20 @@ public:
|
||||
type3::value && type4::value>;
|
||||
};
|
||||
|
||||
template<class B1, class... Bn>
|
||||
struct is_all_ConstBufferSequence
|
||||
: std::integral_constant<bool,
|
||||
is_BufferSequence<B1, boost::asio::const_buffer>::type::value &&
|
||||
is_all_ConstBufferSequence<Bn...>::value>
|
||||
{
|
||||
};
|
||||
|
||||
template<class B1>
|
||||
struct is_all_ConstBufferSequence<B1>
|
||||
: is_BufferSequence<B1, boost::asio::const_buffer>::type
|
||||
{
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class is_DynamicBuffer
|
||||
{
|
||||
|
@@ -5,8 +5,10 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_DETAIL_VOID_T_HPP
|
||||
#define BEAST_DETAIL_VOID_T_HPP
|
||||
#ifndef BEAST_DETAIL_TYPE_TRAITS_HPP
|
||||
#define BEAST_DETAIL_TYPE_TRAITS_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
@@ -33,6 +35,48 @@ void
|
||||
ignore_unused()
|
||||
{}
|
||||
|
||||
template<class U>
|
||||
std::size_t constexpr
|
||||
max_sizeof()
|
||||
{
|
||||
return sizeof(U);
|
||||
}
|
||||
|
||||
template<class U0, class U1, class... Us>
|
||||
std::size_t constexpr
|
||||
max_sizeof()
|
||||
{
|
||||
return
|
||||
max_sizeof<U0>() > max_sizeof<U1, Us...>() ?
|
||||
max_sizeof<U0>() : max_sizeof<U1, Us...>();
|
||||
}
|
||||
|
||||
template<unsigned N, class T, class... Tn>
|
||||
struct repeat_tuple_impl
|
||||
{
|
||||
using type = typename repeat_tuple_impl<
|
||||
N - 1, T, T, Tn...>::type;
|
||||
};
|
||||
|
||||
template<class T, class... Tn>
|
||||
struct repeat_tuple_impl<0, T, Tn...>
|
||||
{
|
||||
using type = std::tuple<T, Tn...>;
|
||||
};
|
||||
|
||||
template<unsigned N, class T>
|
||||
struct repeat_tuple
|
||||
{
|
||||
using type =
|
||||
typename repeat_tuple_impl<N-1, T>::type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct repeat_tuple<0, T>
|
||||
{
|
||||
using type = std::tuple<>;
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // beast
|
||||
|
||||
|
@@ -123,8 +123,10 @@ template<class ConstBufferSequence>
|
||||
#if GENERATING_DOCS
|
||||
implementation_defined
|
||||
#else
|
||||
beast::detail::buffer_cat_helper<boost::asio::const_buffer,
|
||||
chunk_encode_text, ConstBufferSequence, boost::asio::const_buffers_1>
|
||||
beast::detail::buffer_cat_helper<
|
||||
chunk_encode_text,
|
||||
ConstBufferSequence,
|
||||
boost::asio::const_buffers_1>
|
||||
#endif
|
||||
chunk_encode(bool fin, ConstBufferSequence const& buffers)
|
||||
{
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include <boost/asio/streambuf.hpp>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace beast {
|
||||
@@ -20,14 +21,65 @@ namespace beast {
|
||||
class buffer_cat_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
template< class Iterator >
|
||||
template<class Iterator>
|
||||
static
|
||||
std::reverse_iterator<Iterator>
|
||||
make_reverse_iterator( Iterator i )
|
||||
make_reverse_iterator(Iterator i)
|
||||
{
|
||||
return std::reverse_iterator<Iterator>(i);
|
||||
}
|
||||
|
||||
template<class ConstBufferSequence>
|
||||
static
|
||||
std::size_t
|
||||
bsize1(ConstBufferSequence const& bs)
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
std::size_t n = 0;
|
||||
for(auto it = bs.begin(); it != bs.end(); ++it)
|
||||
n += buffer_size(*it);
|
||||
return n;
|
||||
}
|
||||
|
||||
template<class ConstBufferSequence>
|
||||
static
|
||||
std::size_t
|
||||
bsize2(ConstBufferSequence const& bs)
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
std::size_t n = 0;
|
||||
for(auto it = bs.begin(); it != bs.end(); it++)
|
||||
n += buffer_size(*it);
|
||||
return n;
|
||||
}
|
||||
|
||||
template<class ConstBufferSequence>
|
||||
static
|
||||
std::size_t
|
||||
bsize3(ConstBufferSequence const& bs)
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
std::size_t n = 0;
|
||||
for(auto it = bs.end(); it != bs.begin();)
|
||||
n += buffer_size(*--it);
|
||||
return n;
|
||||
}
|
||||
|
||||
template<class ConstBufferSequence>
|
||||
static
|
||||
std::size_t
|
||||
bsize4(ConstBufferSequence const& bs)
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
std::size_t n = 0;
|
||||
for(auto it = bs.end(); it != bs.begin();)
|
||||
{
|
||||
it--;
|
||||
n += buffer_size(*it);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void testBufferCat()
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
@@ -48,6 +100,10 @@ public:
|
||||
auto bs = buffer_cat(
|
||||
b1, b2, b3, b4, b5, b6);
|
||||
BEAST_EXPECT(buffer_size(bs) == 10);
|
||||
BEAST_EXPECT(bsize1(bs) == 10);
|
||||
BEAST_EXPECT(bsize2(bs) == 10);
|
||||
BEAST_EXPECT(bsize3(bs) == 10);
|
||||
BEAST_EXPECT(bsize4(bs) == 10);
|
||||
std::vector<const_buffer> v;
|
||||
for(auto iter = make_reverse_iterator(bs.end());
|
||||
iter != make_reverse_iterator(bs.begin()); ++iter)
|
||||
@@ -55,8 +111,6 @@ public:
|
||||
BEAST_EXPECT(buffer_size(bs) == 10);
|
||||
decltype(bs) bs2(bs);
|
||||
auto bs3(std::move(bs));
|
||||
bs = bs2;
|
||||
bs3 = std::move(bs2);
|
||||
{
|
||||
boost::asio::streambuf sb1, sb2;
|
||||
BEAST_EXPECT(buffer_size(buffer_cat(
|
||||
@@ -153,6 +207,60 @@ public:
|
||||
|
||||
void run() override
|
||||
{
|
||||
using boost::asio::const_buffer;
|
||||
using boost::asio::const_buffers_1;
|
||||
using boost::asio::mutable_buffer;
|
||||
using boost::asio::mutable_buffers_1;
|
||||
struct user_defined : mutable_buffer
|
||||
{
|
||||
};
|
||||
|
||||
// Check is_all_ConstBufferSequence
|
||||
static_assert(
|
||||
detail::is_all_ConstBufferSequence<
|
||||
const_buffers_1
|
||||
>::value, "");
|
||||
static_assert(
|
||||
detail::is_all_ConstBufferSequence<
|
||||
const_buffers_1, const_buffers_1
|
||||
>::value, "");
|
||||
static_assert(
|
||||
detail::is_all_ConstBufferSequence<
|
||||
mutable_buffers_1
|
||||
>::value, "");
|
||||
static_assert(
|
||||
detail::is_all_ConstBufferSequence<
|
||||
mutable_buffers_1, mutable_buffers_1
|
||||
>::value, "");
|
||||
static_assert(
|
||||
detail::is_all_ConstBufferSequence<
|
||||
const_buffers_1, mutable_buffers_1
|
||||
>::value, "");
|
||||
static_assert(
|
||||
! detail::is_all_ConstBufferSequence<
|
||||
const_buffers_1, mutable_buffers_1, int
|
||||
>::value, "");
|
||||
|
||||
// Ensure that concatenating mutable buffer
|
||||
// sequences results in a mutable buffer sequence
|
||||
static_assert(std::is_same<
|
||||
mutable_buffer,
|
||||
decltype(buffer_cat(
|
||||
std::declval<mutable_buffer>(),
|
||||
std::declval<user_defined>(),
|
||||
std::declval<mutable_buffer>()
|
||||
))::value_type>::value, "");
|
||||
|
||||
// Ensure that concatenating mixed buffer
|
||||
// sequences results in a const buffer sequence.
|
||||
static_assert(std::is_same<
|
||||
const_buffer,
|
||||
decltype(buffer_cat(
|
||||
std::declval<mutable_buffer>(),
|
||||
std::declval<user_defined>(),
|
||||
std::declval<const_buffer>()
|
||||
))::value_type>::value, "");
|
||||
|
||||
testBufferCat();
|
||||
testIterators();
|
||||
}
|
||||
|
Reference in New Issue
Block a user