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