mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 21:07:26 +02:00
Refactor buffers_adaptor (API Change):
* Tidy up tests * Increase code coverage * Remove move special members * Correct behavior for default constructed iterators API Changes: * buffers_adaptor is renamed (was buffers_adapter) Actions Required: * Replace buffers_adapter.hpp with buffers_adaptor.hpp, and replace buffers_adapter with buffers_adaptor. Or, define BOOST_BEAST_ALLOW_DEPRECATED
This commit is contained in:
11
CHANGELOG.md
11
CHANGELOG.md
@ -3,6 +3,17 @@ Version 200
|
||||
* Don't include OpenSSL for core snippets
|
||||
* Tidy up msvc-14 workaround in multi_buffer
|
||||
* buffers_cat fixes and coverage
|
||||
* Refactor buffers_adaptor
|
||||
|
||||
API Changes:
|
||||
|
||||
* buffers_adaptor is renamed (was buffers_adapter)
|
||||
|
||||
Actions Required:
|
||||
|
||||
* Replace buffers_adapter.hpp with buffers_adaptor.hpp, and
|
||||
replace buffers_adapter with buffers_adaptor. Or, define
|
||||
BOOST_BEAST_ALLOW_DEPRECATED
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@ -88,7 +88,7 @@ set of additional implementations of the dynamic buffer concept:
|
||||
[table Dynamic Buffer Implementations
|
||||
[[Name][Description]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__buffers_adapter `buffers_adapter`]
|
||||
[link beast.ref.boost__beast__buffers_adaptor `buffers_adaptor`]
|
||||
][
|
||||
This wrapper adapts any __MutableBufferSequence__ into a
|
||||
__DynamicBuffer__ with an upper limit on the total size of the input and
|
||||
|
@ -96,7 +96,7 @@ in future versions.
|
||||
|
||||
* Generated WebSocket masks use a secure PRNG by default
|
||||
|
||||
* Improvements to [link beast.ref.boost__beast__buffers_adapter `buffers_adapter`]
|
||||
* Improvements to [link beast.ref.boost__beast__buffers_adaptor `buffers_adaptor`]
|
||||
|
||||
* ([issue 1188]) Set "/permissive-" for MSVC builds
|
||||
|
||||
@ -134,9 +134,9 @@ in future versions.
|
||||
|
||||
* Fix [link beast.ref.boost__beast__http__parser `http::parser`] constructor javadoc
|
||||
|
||||
* Fix [link beast.ref.boost__beast__buffers_adapter `buffers_adapter`] iterator value type
|
||||
* Fix [link beast.ref.boost__beast__buffers_adaptor `buffers_adaptor`] iterator value type
|
||||
|
||||
* Fix [link beast.ref.boost__beast__buffers_adapter.max_size `buffers_adapter::max_size`]
|
||||
* Fix [link beast.ref.boost__beast__buffers_adaptor.max_size `buffers_adaptor::max_size`]
|
||||
|
||||
* Fix [link beast.ref.boost__beast__buffers_prefix `buffers_prefix`] iterator decrement
|
||||
|
||||
|
@ -180,7 +180,7 @@
|
||||
<member><link linkend="beast.ref.boost__beast__basic_flat_buffer">basic_flat_buffer</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__basic_multi_buffer">basic_multi_buffer</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__buffered_read_stream">buffered_read_stream</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__buffers_adapter">buffers_adapter</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__buffers_adaptor">buffers_adaptor</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__buffers_cat_view">buffers_cat_view</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__buffers_prefix_view">buffers_prefix_view</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__buffers_suffix">buffers_suffix</link></member>
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
#include <boost/beast/_experimental/core/detail/dynamic_buffer_ref.hpp>
|
||||
#include <boost/beast/core/bind_handler.hpp>
|
||||
#include <boost/beast/core/buffers_adapter.hpp>
|
||||
#include <boost/beast/core/buffers_adaptor.hpp>
|
||||
#include <boost/beast/core/buffers_prefix.hpp>
|
||||
#include <boost/beast/core/buffers_suffix.hpp>
|
||||
#include <boost/beast/core/detail/buffers_ref.hpp>
|
||||
@ -132,7 +132,7 @@ class icy_stream<NextLayer>::read_op
|
||||
struct data
|
||||
{
|
||||
icy_stream<NextLayer>& s;
|
||||
buffers_adapter<MutableBufferSequence> b;
|
||||
buffers_adaptor<MutableBufferSequence> b;
|
||||
bool match = false;
|
||||
|
||||
data(
|
||||
@ -234,7 +234,7 @@ operator()(
|
||||
{
|
||||
using iterator = net::buffers_iterator<
|
||||
typename beast::detail::dynamic_buffer_ref<
|
||||
buffers_adapter<MutableBufferSequence>>::const_buffers_type>;
|
||||
buffers_adaptor<MutableBufferSequence>>::const_buffers_type>;
|
||||
auto& d = *d_;
|
||||
BOOST_ASIO_CORO_REENTER(*this)
|
||||
{
|
||||
@ -400,8 +400,8 @@ read_some(MutableBufferSequence const& buffers, error_code& ec)
|
||||
"MutableBufferSequence requirements not met");
|
||||
using iterator = net::buffers_iterator<
|
||||
typename beast::detail::dynamic_buffer_ref<
|
||||
buffers_adapter<MutableBufferSequence>>::const_buffers_type>;
|
||||
buffers_adapter<MutableBufferSequence> b(buffers);
|
||||
buffers_adaptor<MutableBufferSequence>>::const_buffers_type>;
|
||||
buffers_adaptor<MutableBufferSequence> b(buffers);
|
||||
if(b.max_size() == 0)
|
||||
{
|
||||
ec = {};
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <boost/beast/core/bind_handler.hpp>
|
||||
#include <boost/beast/core/buffer_traits.hpp>
|
||||
#include <boost/beast/core/buffered_read_stream.hpp>
|
||||
#include <boost/beast/core/buffers_adapter.hpp>
|
||||
#include <boost/beast/core/buffers_adaptor.hpp>
|
||||
#include <boost/beast/core/buffers_cat.hpp>
|
||||
#include <boost/beast/core/buffers_prefix.hpp>
|
||||
#include <boost/beast/core/buffers_range.hpp>
|
||||
|
@ -11,216 +11,25 @@
|
||||
#define BOOST_BEAST_BUFFERS_ADAPTER_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/core/type_traits.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
#ifdef BOOST_BEAST_ALLOW_DEPRECATED
|
||||
|
||||
#include <boost/beast/core/buffers_adaptor.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
|
||||
/** Adapts a <em>MutableBufferSequence</em> into a <em>DynamicBuffer</em>.
|
||||
|
||||
This class wraps a <em>MutableBufferSequence</em> to meet the requirements
|
||||
of <em>DynamicBuffer</em>. Upon construction the input and output sequences
|
||||
are empty. A copy of the mutable buffer sequence object is stored; however,
|
||||
ownership of the underlying memory is not transferred. The caller is
|
||||
responsible for making sure that referenced memory remains valid
|
||||
for the duration of any operations.
|
||||
|
||||
The size of the mutable buffer sequence determines the maximum
|
||||
number of bytes which may be prepared and committed.
|
||||
|
||||
@tparam MutableBufferSequence The type of mutable buffer sequence to wrap.
|
||||
*/
|
||||
template<class MutableBufferSequence>
|
||||
class buffers_adapter
|
||||
{
|
||||
static_assert(net::is_mutable_buffer_sequence<
|
||||
MutableBufferSequence>::value,
|
||||
"MutableBufferSequence requirements not met");
|
||||
|
||||
using iter_type = typename
|
||||
detail::buffer_sequence_iterator<
|
||||
MutableBufferSequence>::type;
|
||||
|
||||
MutableBufferSequence bs_;
|
||||
iter_type begin_;
|
||||
iter_type out_;
|
||||
iter_type end_;
|
||||
std::size_t max_size_;
|
||||
std::size_t in_pos_ = 0; // offset in *begin_
|
||||
std::size_t in_size_ = 0; // size of input sequence
|
||||
std::size_t out_pos_ = 0; // offset in *out_
|
||||
std::size_t out_end_ = 0; // output end offset
|
||||
|
||||
template<class Deduced>
|
||||
buffers_adapter(Deduced&& other,
|
||||
std::size_t nbegin, std::size_t nout,
|
||||
std::size_t nend)
|
||||
: bs_(std::forward<Deduced>(other).bs_)
|
||||
, begin_(std::next(bs_.begin(), nbegin))
|
||||
, out_(std::next(bs_.begin(), nout))
|
||||
, end_(std::next(bs_.begin(), nend))
|
||||
, max_size_(other.max_size_)
|
||||
, in_pos_(other.in_pos_)
|
||||
, in_size_(other.in_size_)
|
||||
, out_pos_(other.out_pos_)
|
||||
, out_end_(other.out_end_)
|
||||
{
|
||||
}
|
||||
|
||||
iter_type end_impl() const;
|
||||
|
||||
public:
|
||||
/// The type of the underlying mutable buffer sequence
|
||||
using value_type = MutableBufferSequence;
|
||||
|
||||
/// Move constructor.
|
||||
buffers_adapter(buffers_adapter&& other);
|
||||
|
||||
/// Copy constructor.
|
||||
buffers_adapter(buffers_adapter const& other);
|
||||
|
||||
/// Move assignment.
|
||||
buffers_adapter& operator=(buffers_adapter&& other);
|
||||
|
||||
/// Copy assignment.
|
||||
buffers_adapter& operator=(buffers_adapter const&);
|
||||
|
||||
/** Construct a buffers adapter.
|
||||
|
||||
@param buffers The mutable buffer sequence to wrap. A copy of
|
||||
the object will be made, but ownership of the memory is not
|
||||
transferred.
|
||||
*/
|
||||
explicit
|
||||
buffers_adapter(MutableBufferSequence const& buffers);
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs the buffer adapter in-place from
|
||||
a list of arguments.
|
||||
|
||||
@param args Arguments forwarded to the buffers constructor.
|
||||
*/
|
||||
template<class... Args>
|
||||
explicit
|
||||
buffers_adapter(boost::in_place_init_t, Args&&... args);
|
||||
|
||||
/// Returns the original mutable buffer sequence
|
||||
value_type const&
|
||||
value() const
|
||||
{
|
||||
return bs_;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
/// The ConstBufferSequence used to represent the readable bytes.
|
||||
using const_buffers_type = __implementation_defined__;
|
||||
|
||||
/// The MutableBufferSequence used to represent the writable bytes.
|
||||
using mutable_buffers_type = __implementation_defined__;
|
||||
|
||||
#else
|
||||
class const_buffers_type;
|
||||
class mutable_buffers_type;
|
||||
#endif
|
||||
|
||||
/// Returns the number of readable bytes.
|
||||
std::size_t
|
||||
size() const noexcept
|
||||
{
|
||||
return in_size_;
|
||||
}
|
||||
|
||||
/// Return the maximum number of bytes, both readable and writable, that can ever be held.
|
||||
std::size_t
|
||||
max_size() const noexcept
|
||||
{
|
||||
return max_size_;
|
||||
}
|
||||
|
||||
/// Return the maximum number of bytes, both readable and writable, that can be held without requiring an allocation.
|
||||
std::size_t
|
||||
capacity() const noexcept
|
||||
{
|
||||
return max_size_;
|
||||
}
|
||||
|
||||
/// Returns a constant buffer sequence representing the readable bytes
|
||||
const_buffers_type
|
||||
data() const noexcept;
|
||||
|
||||
/** Returns a mutable buffer sequence representing writable bytes.
|
||||
|
||||
Returns a mutable buffer sequence representing the writable
|
||||
bytes containing exactly `n` bytes of storage. This function
|
||||
does not allocate memory. Instead, the storage comes from
|
||||
the underlying mutable buffer sequence.
|
||||
|
||||
All buffer sequences previously obtained using @ref prepare are
|
||||
invalidated. Buffer sequences previously obtained using @ref data
|
||||
remain valid.
|
||||
|
||||
@param n The desired number of bytes in the returned buffer
|
||||
sequence.
|
||||
|
||||
@throws std::length_error if `size() + n` exceeds `max_size()`.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
Strong guarantee.
|
||||
*/
|
||||
mutable_buffers_type
|
||||
prepare(std::size_t n);
|
||||
|
||||
/** Append writable bytes to the readable bytes.
|
||||
|
||||
Appends n bytes from the start of the writable bytes to the
|
||||
end of the readable bytes. The remainder of the writable bytes
|
||||
are discarded. If n is greater than the number of writable
|
||||
bytes, all writable bytes are appended to the readable bytes.
|
||||
|
||||
All buffer sequences previously obtained using @ref prepare are
|
||||
invalidated. Buffer sequences previously obtained using @ref data
|
||||
remain valid.
|
||||
|
||||
@param n The number of bytes to append. If this number
|
||||
is greater than the number of writable bytes, all
|
||||
writable bytes are appended.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
No-throw guarantee.
|
||||
*/
|
||||
void
|
||||
commit(std::size_t n) noexcept;
|
||||
|
||||
/** Remove bytes from beginning of the readable bytes.
|
||||
|
||||
Removes n bytes from the beginning of the readable bytes.
|
||||
|
||||
All buffers sequences previously obtained using
|
||||
@ref data or @ref prepare are invalidated.
|
||||
|
||||
@param n The number of bytes to remove. If this number
|
||||
is greater than the number of readable bytes, all
|
||||
readable bytes are removed.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
No-throw guarantee.
|
||||
*/
|
||||
void
|
||||
consume(std::size_t n) noexcept;
|
||||
};
|
||||
using buffers_adapter = buffers_adaptor<MutableBufferSequence>;
|
||||
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#include <boost/beast/core/impl/buffers_adapter.hpp>
|
||||
#else
|
||||
|
||||
// The new filename is <boost/beast/core/buffers_adaptor.hpp>
|
||||
#error The file <boost/beast/core/buffers_adapter.hpp> is deprecated, define BOOST_BEAST_ALLOW_DEPRECATED to disable this error
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
228
include/boost/beast/core/buffers_adaptor.hpp
Normal file
228
include/boost/beast/core/buffers_adaptor.hpp
Normal file
@ -0,0 +1,228 @@
|
||||
//
|
||||
// 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_BUFFERS_ADAPTOR_HPP
|
||||
#define BOOST_BEAST_BUFFERS_ADAPTOR_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/core/type_traits.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
|
||||
/** Adapts a <em>MutableBufferSequence</em> into a <em>DynamicBuffer</em>.
|
||||
|
||||
This class wraps a <em>MutableBufferSequence</em> to meet the requirements
|
||||
of <em>DynamicBuffer</em>. Upon construction the input and output sequences
|
||||
are empty. A copy of the mutable buffer sequence object is stored; however,
|
||||
ownership of the underlying memory is not transferred. The caller is
|
||||
responsible for making sure that referenced memory remains valid
|
||||
for the duration of any operations.
|
||||
|
||||
The size of the mutable buffer sequence determines the maximum
|
||||
number of bytes which may be prepared and committed.
|
||||
|
||||
@tparam MutableBufferSequence The type of mutable buffer sequence to adapt.
|
||||
*/
|
||||
template<class MutableBufferSequence>
|
||||
class buffers_adaptor
|
||||
{
|
||||
static_assert(net::is_mutable_buffer_sequence<
|
||||
MutableBufferSequence>::value,
|
||||
"MutableBufferSequence requirements not met");
|
||||
|
||||
using iter_type = typename
|
||||
detail::buffer_sequence_iterator<
|
||||
MutableBufferSequence>::type;
|
||||
|
||||
template<bool>
|
||||
class readable_bytes;
|
||||
|
||||
MutableBufferSequence bs_;
|
||||
iter_type begin_;
|
||||
iter_type out_;
|
||||
iter_type end_;
|
||||
std::size_t max_size_;
|
||||
std::size_t in_pos_ = 0; // offset in *begin_
|
||||
std::size_t in_size_ = 0; // size of input sequence
|
||||
std::size_t out_pos_ = 0; // offset in *out_
|
||||
std::size_t out_end_ = 0; // output end offset
|
||||
|
||||
iter_type end_impl() const;
|
||||
|
||||
buffers_adaptor(
|
||||
buffers_adaptor const& other,
|
||||
std::size_t nbegin,
|
||||
std::size_t nout,
|
||||
std::size_t nend);
|
||||
|
||||
public:
|
||||
/// The type of the underlying mutable buffer sequence
|
||||
using value_type = MutableBufferSequence;
|
||||
|
||||
/** Construct a buffers adaptor.
|
||||
|
||||
@param buffers The mutable buffer sequence to wrap. A copy of
|
||||
the object will be made, but ownership of the memory is not
|
||||
transferred.
|
||||
*/
|
||||
explicit
|
||||
buffers_adaptor(MutableBufferSequence const& buffers);
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs the buffer adaptor in-place from
|
||||
a list of arguments.
|
||||
|
||||
@param args Arguments forwarded to the buffers constructor.
|
||||
*/
|
||||
template<class... Args>
|
||||
explicit
|
||||
buffers_adaptor(boost::in_place_init_t, Args&&... args);
|
||||
|
||||
/// Copy Constructor
|
||||
buffers_adaptor(buffers_adaptor const& other);
|
||||
|
||||
/// Copy Assignment
|
||||
buffers_adaptor& operator=(buffers_adaptor const&);
|
||||
|
||||
/// Returns the original mutable buffer sequence
|
||||
value_type const&
|
||||
value() const
|
||||
{
|
||||
return bs_;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
/// The ConstBufferSequence used to represent the readable bytes.
|
||||
using const_buffers_type = __implementation_defined__;
|
||||
|
||||
/// The MutableBufferSequence used to represent the readable bytes.
|
||||
using mutable_data_type = __implementation_defined__;
|
||||
|
||||
/// The MutableBufferSequence used to represent the writable bytes.
|
||||
using mutable_buffers_type = __implementation_defined__;
|
||||
|
||||
#else
|
||||
using const_buffers_type = readable_bytes<false>;
|
||||
using mutable_data_type = readable_bytes<true>;
|
||||
class mutable_buffers_type;
|
||||
#endif
|
||||
|
||||
/// Returns the number of readable bytes.
|
||||
std::size_t
|
||||
size() const noexcept
|
||||
{
|
||||
return in_size_;
|
||||
}
|
||||
|
||||
/// Return the maximum number of bytes, both readable and writable, that can ever be held.
|
||||
std::size_t
|
||||
max_size() const noexcept
|
||||
{
|
||||
return max_size_;
|
||||
}
|
||||
|
||||
/// Return the maximum number of bytes, both readable and writable, that can be held without requiring an allocation.
|
||||
std::size_t
|
||||
capacity() const noexcept
|
||||
{
|
||||
return max_size_;
|
||||
}
|
||||
|
||||
/// Returns a constant buffer sequence representing the readable bytes
|
||||
const_buffers_type
|
||||
data() const noexcept;
|
||||
|
||||
/// Returns a constant buffer sequence representing the readable bytes
|
||||
const_buffers_type
|
||||
cdata() const noexcept
|
||||
{
|
||||
return data();
|
||||
}
|
||||
|
||||
/// Returns a mutable buffer sequence representing the readable bytes.
|
||||
mutable_data_type
|
||||
data() noexcept;
|
||||
|
||||
/** Returns a mutable buffer sequence representing writable bytes.
|
||||
|
||||
Returns a mutable buffer sequence representing the writable
|
||||
bytes containing exactly `n` bytes of storage. This function
|
||||
does not allocate memory. Instead, the storage comes from
|
||||
the underlying mutable buffer sequence.
|
||||
|
||||
All buffer sequences previously obtained using @ref prepare are
|
||||
invalidated. Buffer sequences previously obtained using @ref data
|
||||
remain valid.
|
||||
|
||||
@param n The desired number of bytes in the returned buffer
|
||||
sequence.
|
||||
|
||||
@throws std::length_error if `size() + n` exceeds `max_size()`.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
Strong guarantee.
|
||||
*/
|
||||
mutable_buffers_type
|
||||
prepare(std::size_t n);
|
||||
|
||||
/** Append writable bytes to the readable bytes.
|
||||
|
||||
Appends n bytes from the start of the writable bytes to the
|
||||
end of the readable bytes. The remainder of the writable bytes
|
||||
are discarded. If n is greater than the number of writable
|
||||
bytes, all writable bytes are appended to the readable bytes.
|
||||
|
||||
All buffer sequences previously obtained using @ref prepare are
|
||||
invalidated. Buffer sequences previously obtained using @ref data
|
||||
remain valid.
|
||||
|
||||
@param n The number of bytes to append. If this number
|
||||
is greater than the number of writable bytes, all
|
||||
writable bytes are appended.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
No-throw guarantee.
|
||||
*/
|
||||
void
|
||||
commit(std::size_t n) noexcept;
|
||||
|
||||
/** Remove bytes from beginning of the readable bytes.
|
||||
|
||||
Removes n bytes from the beginning of the readable bytes.
|
||||
|
||||
All buffers sequences previously obtained using
|
||||
@ref data or @ref prepare are invalidated.
|
||||
|
||||
@param n The number of bytes to remove. If this number
|
||||
is greater than the number of readable bytes, all
|
||||
readable bytes are removed.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
No-throw guarantee.
|
||||
*/
|
||||
void
|
||||
consume(std::size_t n) noexcept;
|
||||
};
|
||||
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#include <boost/beast/core/impl/buffers_adaptor.hpp>
|
||||
|
||||
#endif
|
@ -7,37 +7,84 @@
|
||||
// Official repository: https://github.com/boostorg/beast
|
||||
//
|
||||
|
||||
#ifndef BOOST_BEAST_IMPL_BUFFERS_ADAPTER_IPP
|
||||
#define BOOST_BEAST_IMPL_BUFFERS_ADAPTER_IPP
|
||||
#ifndef BOOST_BEAST_IMPL_BUFFERS_ADAPTOR_HPP
|
||||
#define BOOST_BEAST_IMPL_BUFFERS_ADAPTOR_HPP
|
||||
|
||||
#include <boost/beast/core/detail/type_traits.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
|
||||
# pragma warning (push)
|
||||
# pragma warning (disable: 4521) // multiple copy constructors specified
|
||||
# pragma warning (disable: 4522) // multiple assignment operators specified
|
||||
#endif
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
class buffers_adapter<MutableBufferSequence>::
|
||||
const_buffers_type
|
||||
template<bool isMutable>
|
||||
class buffers_adaptor<MutableBufferSequence>::
|
||||
readable_bytes
|
||||
{
|
||||
buffers_adapter const* b_;
|
||||
buffers_adaptor const* b_;
|
||||
|
||||
public:
|
||||
using value_type = net::const_buffer;
|
||||
using value_type = typename
|
||||
std::conditional<isMutable,
|
||||
net::mutable_buffer,
|
||||
net::const_buffer>::type;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
const_buffers_type() = delete;
|
||||
const_buffers_type(
|
||||
const_buffers_type const&) = default;
|
||||
const_buffers_type& operator=(
|
||||
const_buffers_type const&) = default;
|
||||
readable_bytes() = delete;
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
|
||||
readable_bytes(
|
||||
readable_bytes const& other)
|
||||
: b_(other.b_)
|
||||
{
|
||||
}
|
||||
|
||||
readable_bytes& operator=(
|
||||
readable_bytes const& other)
|
||||
{
|
||||
b_ = other.b_;
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
readable_bytes(
|
||||
readable_bytes const&) = default;
|
||||
readable_bytes& operator=(
|
||||
readable_bytes const&) = default;
|
||||
#endif
|
||||
|
||||
template<bool isMutable_ = isMutable, class =
|
||||
typename std::enable_if<! isMutable_>::type>
|
||||
readable_bytes(
|
||||
readable_bytes<true> const& other) noexcept
|
||||
: b_(other.b_)
|
||||
{
|
||||
}
|
||||
|
||||
template<bool isMutable_ = isMutable, class =
|
||||
typename std::enable_if<! isMutable_>::type>
|
||||
readable_bytes& operator=(
|
||||
readable_bytes<true> const& other) noexcept
|
||||
{
|
||||
b_ = other.b_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
@ -46,23 +93,34 @@ public:
|
||||
end() const;
|
||||
|
||||
private:
|
||||
friend class buffers_adapter;
|
||||
friend class buffers_adaptor;
|
||||
|
||||
const_buffers_type(buffers_adapter const& b)
|
||||
readable_bytes(buffers_adaptor const& b)
|
||||
: b_(&b)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
|
||||
# pragma warning (pop)
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
class buffers_adapter<MutableBufferSequence>::
|
||||
const_buffers_type::const_iterator
|
||||
template<bool isMutable>
|
||||
class buffers_adaptor<MutableBufferSequence>::
|
||||
readable_bytes<isMutable>::
|
||||
const_iterator
|
||||
{
|
||||
iter_type it_;
|
||||
buffers_adapter const* b_ = nullptr;
|
||||
buffers_adaptor const* b_ = nullptr;
|
||||
|
||||
public:
|
||||
using value_type = net::const_buffer;
|
||||
using value_type = typename
|
||||
std::conditional<isMutable,
|
||||
net::mutable_buffer,
|
||||
net::const_buffer>::type;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
@ -70,28 +128,13 @@ public:
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return
|
||||
(b_ == nullptr) ?
|
||||
(
|
||||
other.b_ == nullptr ||
|
||||
other.it_ == other.b_->end_impl()
|
||||
):(
|
||||
(other.b_ == nullptr) ?
|
||||
(
|
||||
it_ == b_->end_impl()
|
||||
): (
|
||||
b_ == other.b_ &&
|
||||
it_ == other.it_
|
||||
)
|
||||
);
|
||||
return b_ == other.b_ && it_ == other.it_;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -144,10 +187,11 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
friend class const_buffers_type;
|
||||
friend class readable_bytes;
|
||||
|
||||
const_iterator(buffers_adapter const& b,
|
||||
iter_type iter)
|
||||
const_iterator(
|
||||
buffers_adaptor const& b,
|
||||
iter_type iter)
|
||||
: it_(iter)
|
||||
, b_(&b)
|
||||
{
|
||||
@ -155,18 +199,22 @@ private:
|
||||
};
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
template<bool isMutable>
|
||||
auto
|
||||
buffers_adapter<MutableBufferSequence>::
|
||||
const_buffers_type::begin() const ->
|
||||
buffers_adaptor<MutableBufferSequence>::
|
||||
readable_bytes<isMutable>::
|
||||
begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*b_, b_->begin_};
|
||||
}
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
template<bool isMutable>
|
||||
auto
|
||||
buffers_adapter<MutableBufferSequence>::
|
||||
const_buffers_type::end() const ->
|
||||
buffers_adaptor<MutableBufferSequence>::
|
||||
readable_bytes<isMutable>::
|
||||
readable_bytes::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*b_, b_->end_impl()};
|
||||
@ -175,10 +223,10 @@ const_buffers_type::end() const ->
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
class buffers_adapter<MutableBufferSequence>::
|
||||
class buffers_adaptor<MutableBufferSequence>::
|
||||
mutable_buffers_type
|
||||
{
|
||||
buffers_adapter const* b_;
|
||||
buffers_adaptor const* b_;
|
||||
|
||||
public:
|
||||
using value_type = net::mutable_buffer;
|
||||
@ -198,21 +246,21 @@ public:
|
||||
end() const;
|
||||
|
||||
private:
|
||||
friend class buffers_adapter;
|
||||
friend class buffers_adaptor;
|
||||
|
||||
mutable_buffers_type(
|
||||
buffers_adapter const& b)
|
||||
buffers_adaptor const& b)
|
||||
: b_(&b)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
class buffers_adapter<MutableBufferSequence>::
|
||||
class buffers_adaptor<MutableBufferSequence>::
|
||||
mutable_buffers_type::const_iterator
|
||||
{
|
||||
iter_type it_;
|
||||
buffers_adapter const* b_ = nullptr;
|
||||
buffers_adaptor const* b_ = nullptr;
|
||||
|
||||
public:
|
||||
using value_type = net::mutable_buffer;
|
||||
@ -223,28 +271,13 @@ public:
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return
|
||||
(b_ == nullptr) ?
|
||||
(
|
||||
other.b_ == nullptr ||
|
||||
other.it_ == other.b_->end_
|
||||
):(
|
||||
(other.b_ == nullptr) ?
|
||||
(
|
||||
it_ == b_->end_
|
||||
): (
|
||||
b_ == other.b_ &&
|
||||
it_ == other.it_
|
||||
)
|
||||
);
|
||||
return b_ == other.b_ && it_ == other.it_;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -299,7 +332,7 @@ public:
|
||||
private:
|
||||
friend class mutable_buffers_type;
|
||||
|
||||
const_iterator(buffers_adapter const& b,
|
||||
const_iterator(buffers_adaptor const& b,
|
||||
iter_type iter)
|
||||
: it_(iter)
|
||||
, b_(&b)
|
||||
@ -309,7 +342,7 @@ private:
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
auto
|
||||
buffers_adapter<MutableBufferSequence>::
|
||||
buffers_adaptor<MutableBufferSequence>::
|
||||
mutable_buffers_type::
|
||||
begin() const ->
|
||||
const_iterator
|
||||
@ -319,7 +352,7 @@ begin() const ->
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
auto
|
||||
buffers_adapter<MutableBufferSequence>::
|
||||
buffers_adaptor<MutableBufferSequence>::
|
||||
mutable_buffers_type::
|
||||
end() const ->
|
||||
const_iterator
|
||||
@ -331,7 +364,7 @@ end() const ->
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
auto
|
||||
buffers_adapter<MutableBufferSequence>::
|
||||
buffers_adaptor<MutableBufferSequence>::
|
||||
end_impl() const ->
|
||||
iter_type
|
||||
{
|
||||
@ -339,57 +372,75 @@ end_impl() const ->
|
||||
}
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
buffers_adapter<MutableBufferSequence>::
|
||||
buffers_adapter(buffers_adapter&& other)
|
||||
: buffers_adapter(std::move(other),
|
||||
std::distance<iter_type>(net::buffer_sequence_begin(other.bs_), other.begin_),
|
||||
std::distance<iter_type>(net::buffer_sequence_begin(other.bs_), other.out_),
|
||||
std::distance<iter_type>(net::buffer_sequence_begin(other.bs_), other.end_))
|
||||
buffers_adaptor<MutableBufferSequence>::
|
||||
buffers_adaptor(
|
||||
buffers_adaptor const& other,
|
||||
std::size_t nbegin,
|
||||
std::size_t nout,
|
||||
std::size_t nend)
|
||||
: bs_(other.bs_)
|
||||
, begin_(std::next(bs_.begin(), nbegin))
|
||||
, out_(std::next(bs_.begin(), nout))
|
||||
, end_(std::next(bs_.begin(), nend))
|
||||
, max_size_(other.max_size_)
|
||||
, in_pos_(other.in_pos_)
|
||||
, in_size_(other.in_size_)
|
||||
, out_pos_(other.out_pos_)
|
||||
, out_end_(other.out_end_)
|
||||
{
|
||||
}
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
buffers_adapter<MutableBufferSequence>::
|
||||
buffers_adapter(buffers_adapter const& other)
|
||||
: buffers_adapter(other,
|
||||
std::distance<iter_type>(net::buffer_sequence_begin(other.bs_), other.begin_),
|
||||
std::distance<iter_type>(net::buffer_sequence_begin(other.bs_), other.out_),
|
||||
std::distance<iter_type>(net::buffer_sequence_begin(other.bs_), other.end_))
|
||||
buffers_adaptor<MutableBufferSequence>::
|
||||
buffers_adaptor(MutableBufferSequence const& bs)
|
||||
: bs_(bs)
|
||||
, begin_(net::buffer_sequence_begin(bs_))
|
||||
, out_ (net::buffer_sequence_begin(bs_))
|
||||
, end_ (net::buffer_sequence_begin(bs_))
|
||||
, max_size_(
|
||||
[&bs]
|
||||
{
|
||||
using net::buffer_size;
|
||||
return buffer_size(bs);
|
||||
}())
|
||||
{
|
||||
}
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
template<class... Args>
|
||||
buffers_adaptor<MutableBufferSequence>::
|
||||
buffers_adaptor(
|
||||
boost::in_place_init_t, Args&&... args)
|
||||
: bs_{std::forward<Args>(args)...}
|
||||
, begin_(net::buffer_sequence_begin(bs_))
|
||||
, out_ (net::buffer_sequence_begin(bs_))
|
||||
, end_ (net::buffer_sequence_begin(bs_))
|
||||
, max_size_(net::buffer_size(bs_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
buffers_adaptor<MutableBufferSequence>::
|
||||
buffers_adaptor(buffers_adaptor const& other)
|
||||
: buffers_adaptor(
|
||||
other,
|
||||
std::distance<iter_type>(
|
||||
net::buffer_sequence_begin(other.bs_),
|
||||
other.begin_),
|
||||
std::distance<iter_type>(
|
||||
net::buffer_sequence_begin(other.bs_),
|
||||
other.out_),
|
||||
std::distance<iter_type>(
|
||||
net::buffer_sequence_begin(other.bs_),
|
||||
other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
auto
|
||||
buffers_adapter<MutableBufferSequence>::
|
||||
operator=(buffers_adapter&& other) ->
|
||||
buffers_adapter&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
net::buffer_sequence_begin(other.bs_),
|
||||
other.begin_);
|
||||
auto const nout = std::distance<iter_type>(
|
||||
net::buffer_sequence_begin(other.bs_),
|
||||
other.out_);
|
||||
auto const nend = std::distance<iter_type>(
|
||||
net::buffer_sequence_begin(other.bs_),
|
||||
other.end_);
|
||||
bs_ = std::move(other.bs_);
|
||||
begin_ = std::next(net::buffer_sequence_begin(bs_), nbegin);
|
||||
out_ = std::next(net::buffer_sequence_begin(bs_), nout);
|
||||
end_ = std::next(net::buffer_sequence_begin(bs_), nend);
|
||||
max_size_ = other.max_size_;
|
||||
in_pos_ = other.in_pos_;
|
||||
in_size_ = other.in_size_;
|
||||
out_pos_ = other.out_pos_;
|
||||
out_end_ = other.out_end_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
auto
|
||||
buffers_adapter<MutableBufferSequence>::
|
||||
operator=(buffers_adapter const& other) ->
|
||||
buffers_adapter&
|
||||
buffers_adaptor<MutableBufferSequence>::
|
||||
operator=(buffers_adaptor const& other) ->
|
||||
buffers_adaptor&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
net::buffer_sequence_begin(other.bs_),
|
||||
@ -401,9 +452,12 @@ operator=(buffers_adapter const& other) ->
|
||||
net::buffer_sequence_begin(other.bs_),
|
||||
other.end_);
|
||||
bs_ = other.bs_;
|
||||
begin_ = std::next(net::buffer_sequence_begin(bs_), nbegin);
|
||||
out_ = std::next(net::buffer_sequence_begin(bs_), nout);
|
||||
end_ = std::next(net::buffer_sequence_begin(bs_), nend);
|
||||
begin_ = std::next(
|
||||
net::buffer_sequence_begin(bs_), nbegin);
|
||||
out_ = std::next(
|
||||
net::buffer_sequence_begin(bs_), nout);
|
||||
end_ = std::next(
|
||||
net::buffer_sequence_begin(bs_), nend);
|
||||
max_size_ = other.max_size_;
|
||||
in_pos_ = other.in_pos_;
|
||||
in_size_ = other.in_size_;
|
||||
@ -412,47 +466,43 @@ operator=(buffers_adapter const& other) ->
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
buffers_adapter<MutableBufferSequence>::
|
||||
buffers_adapter(MutableBufferSequence const& bs)
|
||||
: bs_(bs)
|
||||
, begin_(net::buffer_sequence_begin(bs_))
|
||||
, out_ (net::buffer_sequence_begin(bs_))
|
||||
, end_ (net::buffer_sequence_begin(bs_))
|
||||
, max_size_(net::buffer_size(bs_))
|
||||
{
|
||||
}
|
||||
//
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
template<class... Args>
|
||||
buffers_adapter<MutableBufferSequence>::
|
||||
buffers_adapter(boost::in_place_init_t, Args&&... args)
|
||||
: bs_{std::forward<Args>(args)...}
|
||||
, begin_(net::buffer_sequence_begin(bs_))
|
||||
, out_ (net::buffer_sequence_begin(bs_))
|
||||
, end_ (net::buffer_sequence_begin(bs_))
|
||||
, max_size_(net::buffer_size(bs_))
|
||||
auto
|
||||
buffers_adaptor<MutableBufferSequence>::
|
||||
data() const noexcept ->
|
||||
const_buffers_type
|
||||
{
|
||||
return const_buffers_type{*this};
|
||||
}
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
auto
|
||||
buffers_adapter<MutableBufferSequence>::
|
||||
buffers_adaptor<MutableBufferSequence>::
|
||||
data() noexcept ->
|
||||
mutable_data_type
|
||||
{
|
||||
return mutable_data_type{*this};
|
||||
}
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
auto
|
||||
buffers_adaptor<MutableBufferSequence>::
|
||||
prepare(std::size_t n) ->
|
||||
mutable_buffers_type
|
||||
{
|
||||
using net::buffer_size;
|
||||
end_ = out_;
|
||||
if(end_ != net::buffer_sequence_end(bs_))
|
||||
{
|
||||
auto size = buffer_size(*end_) - out_pos_;
|
||||
auto size = net::buffer_size(*end_) - out_pos_;
|
||||
if(n > size)
|
||||
{
|
||||
n -= size;
|
||||
while(++end_ !=
|
||||
net::buffer_sequence_end(bs_))
|
||||
{
|
||||
size = buffer_size(*end_);
|
||||
size = net::buffer_size(*end_);
|
||||
if(n < size)
|
||||
{
|
||||
out_end_ = n;
|
||||
@ -473,22 +523,13 @@ prepare(std::size_t n) ->
|
||||
}
|
||||
if(n > 0)
|
||||
BOOST_THROW_EXCEPTION(std::length_error{
|
||||
"buffer overflow"});
|
||||
"buffers_adaptor too long"});
|
||||
return mutable_buffers_type{*this};
|
||||
}
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
auto
|
||||
buffers_adapter<MutableBufferSequence>::
|
||||
data() const noexcept ->
|
||||
const_buffers_type
|
||||
{
|
||||
return const_buffers_type{*this};
|
||||
}
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
void
|
||||
buffers_adapter<MutableBufferSequence>::
|
||||
buffers_adaptor<MutableBufferSequence>::
|
||||
commit(std::size_t n) noexcept
|
||||
{
|
||||
if(out_ == end_)
|
||||
@ -524,7 +565,7 @@ commit(std::size_t n) noexcept
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
void
|
||||
buffers_adapter<MutableBufferSequence>::
|
||||
buffers_adaptor<MutableBufferSequence>::
|
||||
consume(std::size_t n) noexcept
|
||||
{
|
||||
while(begin_ != out_)
|
@ -22,6 +22,7 @@ add_executable (tests-beast-core
|
||||
buffer_traits.cpp
|
||||
buffered_read_stream.cpp
|
||||
buffers_adapter.cpp
|
||||
buffers_adaptor.cpp
|
||||
buffers_cat.cpp
|
||||
buffers_prefix.cpp
|
||||
buffers_range.cpp
|
||||
@ -39,9 +40,9 @@ add_executable (tests-beast-core
|
||||
ostream.cpp
|
||||
read_size.cpp
|
||||
span.cpp
|
||||
static_buffer.cpp
|
||||
static_string.cpp
|
||||
string.cpp
|
||||
static_buffer.cpp
|
||||
string_param.cpp
|
||||
type_traits.cpp
|
||||
detail_base64.cpp
|
||||
|
@ -12,6 +12,7 @@ local SOURCES =
|
||||
buffer_traits.cpp
|
||||
buffered_read_stream.cpp
|
||||
buffers_adapter.cpp
|
||||
buffers_adaptor.cpp
|
||||
buffers_cat.cpp
|
||||
buffers_prefix.cpp
|
||||
buffers_range.cpp
|
||||
|
@ -10,18 +10,101 @@
|
||||
#ifndef BOOST_BEAST_TEST_BUFFER_TEST_HPP
|
||||
#define BOOST_BEAST_TEST_BUFFER_TEST_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
#include <boost/beast/core/buffer_traits.hpp>
|
||||
#include <boost/beast/core/buffers_to_string.hpp>
|
||||
#include <boost/beast/core/string.hpp>
|
||||
#include <boost/beast/core/read_size.hpp>
|
||||
#include <boost/beast/core/type_traits.hpp>
|
||||
#include <boost/beast/core/detail/type_traits.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/buffers_iterator.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// VFALCO This is here temporarily
|
||||
|
||||
#define SUITE_EXPECT(test, cond) \
|
||||
((test).expect((cond), __FILE__, __LINE__))
|
||||
|
||||
#define SUITE_EXPECTS(test, cond, reason) \
|
||||
((cond) ? ((test).pass(), true) \
|
||||
: ((test).fail((reason), __FILE__, __LINE__), false))
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A MutableBufferSequence for tests, where length is always 3.
|
||||
*/
|
||||
class buffers_triple
|
||||
{
|
||||
net::mutable_buffer b_[3];
|
||||
|
||||
public:
|
||||
using value_type = net::mutable_buffer;
|
||||
using const_iterator = net::mutable_buffer const*;
|
||||
|
||||
buffers_triple(
|
||||
buffers_triple const&) = default;
|
||||
buffers_triple& operator=(
|
||||
buffers_triple const&) = default;
|
||||
|
||||
buffers_triple(char* data, std::size_t size)
|
||||
{
|
||||
b_[0] = {data, size/6};
|
||||
data += b_[0].size();
|
||||
size -= b_[0].size();
|
||||
|
||||
b_[1] = {data, 2*size/5};
|
||||
data += b_[1].size();
|
||||
size -= b_[1].size();
|
||||
|
||||
b_[2] = {data, size};
|
||||
|
||||
BOOST_ASSERT(b_[0].size() > 0);
|
||||
BOOST_ASSERT(b_[1].size() > 0);
|
||||
BOOST_ASSERT(b_[2].size() > 0);
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(buffers_triple const& rhs) const noexcept
|
||||
{
|
||||
return
|
||||
b_[0].data() == rhs.b_[0].data() &&
|
||||
b_[0].size() == rhs.b_[0].size() &&
|
||||
b_[1].data() == rhs.b_[1].data() &&
|
||||
b_[1].size() == rhs.b_[1].size() &&
|
||||
b_[2].data() == rhs.b_[2].data() &&
|
||||
b_[2].size() == rhs.b_[2].size();
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(buffers_triple const& rhs) const noexcept
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
const_iterator
|
||||
begin() const noexcept
|
||||
{
|
||||
return &b_[0];
|
||||
}
|
||||
|
||||
const_iterator
|
||||
end() const noexcept
|
||||
{
|
||||
return &b_[3];
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace test {
|
||||
|
||||
template<class DynamicBuffer>
|
||||
@ -101,6 +184,397 @@ size_rev_post(ConstBufferSequence const& buffers)
|
||||
}
|
||||
|
||||
} // test
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
void test_mutable_buffers(
|
||||
unit_test::suite&,
|
||||
MutableBufferSequence const&,
|
||||
net::const_buffer)
|
||||
{
|
||||
}
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
void test_mutable_buffers(
|
||||
unit_test::suite& test,
|
||||
MutableBufferSequence const& b,
|
||||
net::mutable_buffer)
|
||||
{
|
||||
using net::buffer_size;
|
||||
string_view src = "Hello, world!";
|
||||
if(src.size() > buffer_size(b))
|
||||
src = {src.data(), buffer_size(b)};
|
||||
net::buffer_copy(b, net::const_buffer(
|
||||
src.data(), src.size()));
|
||||
SUITE_EXPECT(test,
|
||||
beast::buffers_to_string(b) == src);
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
/** Test an instance of a constant or mutable buffer sequence.
|
||||
*/
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
test_buffer_sequence(
|
||||
beast::unit_test::suite& test,
|
||||
ConstBufferSequence const& buffers)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
net::is_const_buffer_sequence<
|
||||
ConstBufferSequence>::value);
|
||||
|
||||
using net::buffer_size;
|
||||
|
||||
using iterator = decltype(
|
||||
net::buffer_sequence_begin(buffers));
|
||||
SUITE_EXPECT(test, sizeof(iterator) > 0);
|
||||
|
||||
auto const size = buffer_size(buffers);
|
||||
SUITE_EXPECT(test, size > 0 );
|
||||
|
||||
// begin, end
|
||||
auto const length = std::distance(
|
||||
net::buffer_sequence_begin(buffers),
|
||||
net::buffer_sequence_end(buffers));
|
||||
SUITE_EXPECT(test, length > 0);
|
||||
SUITE_EXPECT(test,
|
||||
net::buffer_sequence_begin(buffers) !=
|
||||
net::buffer_sequence_end(buffers));
|
||||
|
||||
// copy construction
|
||||
ConstBufferSequence b1(buffers);
|
||||
SUITE_EXPECT(test, buffer_size(b1) == size);
|
||||
|
||||
// copy assignment
|
||||
ConstBufferSequence b2(buffers);
|
||||
b2 = b1;
|
||||
SUITE_EXPECT(test, buffer_size(b2) == size);
|
||||
|
||||
// iterators
|
||||
{
|
||||
iterator it1{};
|
||||
iterator it2{};
|
||||
iterator it3 =
|
||||
net::buffer_sequence_begin(buffers);
|
||||
iterator it4 =
|
||||
net::buffer_sequence_end(buffers);
|
||||
SUITE_EXPECT(test, it1 == it2);
|
||||
SUITE_EXPECT(test, it1 != it3);
|
||||
SUITE_EXPECT(test, it3 != it1);
|
||||
SUITE_EXPECT(test, it1 != it4);
|
||||
SUITE_EXPECT(test, it4 != it1);
|
||||
}
|
||||
|
||||
// bidirectional
|
||||
{
|
||||
auto const first =
|
||||
net::buffer_sequence_begin(buffers);
|
||||
auto const last =
|
||||
net::buffer_sequence_end(buffers);
|
||||
std::size_t n, m;
|
||||
iterator it;
|
||||
|
||||
// pre-increment
|
||||
m = 0;
|
||||
n = length;
|
||||
for(it = first; n--; ++it)
|
||||
m += net::buffer_size(*it);
|
||||
SUITE_EXPECT(test, it == last);
|
||||
SUITE_EXPECT(test, m == size);
|
||||
|
||||
// post-increment
|
||||
m = 0;
|
||||
n = length;
|
||||
for(it = first; n--;)
|
||||
m += net::buffer_size(*it++);
|
||||
SUITE_EXPECT(test, it == last);
|
||||
SUITE_EXPECT(test, m == size);
|
||||
|
||||
// pre-decrement
|
||||
m = 0;
|
||||
n = length;
|
||||
for(it = last; n--;)
|
||||
m += net::buffer_size(*--it);
|
||||
SUITE_EXPECT(test, it == first);
|
||||
SUITE_EXPECT(test, m == size);
|
||||
|
||||
// post-decrement
|
||||
m = 0;
|
||||
n = length;
|
||||
for(it = last; n--;)
|
||||
{
|
||||
it--;
|
||||
m += net::buffer_size(*it);
|
||||
}
|
||||
SUITE_EXPECT(test, it == first);
|
||||
SUITE_EXPECT(test, m == size);
|
||||
}
|
||||
|
||||
detail::test_mutable_buffers(test, buffers,
|
||||
buffers_type<ConstBufferSequence>{});
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Metafunction to determine if a type meets the requirements of MutableDynamicBuffer
|
||||
*/
|
||||
/* @{ */
|
||||
// VFALCO This trait needs tests
|
||||
template<class T, class = void>
|
||||
struct is_mutable_dynamic_buffer
|
||||
: std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_mutable_dynamic_buffer<T, detail::void_t<decltype(
|
||||
std::declval<typename T::const_buffers_type&>() =
|
||||
std::declval<T const&>().data(),
|
||||
std::declval<typename T::const_buffers_type&>() =
|
||||
std::declval<T&>().cdata(),
|
||||
std::declval<typename T::mutable_data_type&>() =
|
||||
std::declval<T&>().data()
|
||||
) > > : net::is_dynamic_buffer<T>
|
||||
{
|
||||
};
|
||||
/** @} */
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class MutableDynamicBuffer>
|
||||
void
|
||||
test_mutable_dynamic_buffer(
|
||||
unit_test::suite&,
|
||||
MutableDynamicBuffer const&,
|
||||
std::false_type)
|
||||
{
|
||||
}
|
||||
|
||||
template<class MutableDynamicBuffer>
|
||||
void
|
||||
test_mutable_dynamic_buffer(
|
||||
unit_test::suite& test,
|
||||
MutableDynamicBuffer const& b0,
|
||||
std::true_type)
|
||||
{
|
||||
using net::buffer_size;
|
||||
|
||||
BOOST_STATIC_ASSERT(
|
||||
net::is_mutable_buffer_sequence<typename
|
||||
MutableDynamicBuffer::mutable_data_type>::value);
|
||||
|
||||
string_view src = "Hello, world!";
|
||||
if(src.size() > b0.max_size())
|
||||
src = {src.data(), b0.max_size()};
|
||||
|
||||
// modify readable bytes
|
||||
{
|
||||
MutableDynamicBuffer b(b0);
|
||||
auto const mb = b.prepare(src.size());
|
||||
using iter_type = net::buffers_iterator<decltype(mb)>;
|
||||
SUITE_EXPECT(test, buffer_size(mb) == src.size());
|
||||
std::fill(
|
||||
iter_type::begin(mb),
|
||||
iter_type::end(mb), '*');
|
||||
b.commit(src.size());
|
||||
SUITE_EXPECT(test, b.size() == src.size());
|
||||
SUITE_EXPECT(test,
|
||||
beast::buffers_to_string(b.data()) ==
|
||||
std::string(src.size(), '*'));
|
||||
SUITE_EXPECT(test,
|
||||
beast::buffers_to_string(b.cdata()) ==
|
||||
std::string(src.size(), '*'));
|
||||
auto const n = net::buffer_copy(
|
||||
b.data(), net::const_buffer(
|
||||
src.data(), src.size()));
|
||||
SUITE_EXPECT(test, n == src.size());
|
||||
SUITE_EXPECT(test,
|
||||
beast::buffers_to_string(b.data()) == src);
|
||||
SUITE_EXPECT(test,
|
||||
beast::buffers_to_string(b.cdata()) == src);
|
||||
}
|
||||
|
||||
// mutable to const sequence conversion
|
||||
{
|
||||
MutableDynamicBuffer b(b0);
|
||||
b.commit(net::buffer_copy(
|
||||
b.prepare(src.size()),
|
||||
net::const_buffer(src.data(), src.size())));
|
||||
auto mb = b.data();
|
||||
auto cb = static_cast<
|
||||
MutableDynamicBuffer const&>(b).data();
|
||||
auto cbc = b.cdata();
|
||||
SUITE_EXPECT(test,
|
||||
beast::buffers_to_string(b.data()) == src);
|
||||
SUITE_EXPECT(test,
|
||||
beast::buffers_to_string(b.cdata()) == src);
|
||||
beast::test_buffer_sequence(test, cb);
|
||||
beast::test_buffer_sequence(test, cbc);
|
||||
beast::test_buffer_sequence(test, mb);
|
||||
{
|
||||
decltype(mb) mb2(mb);
|
||||
mb = mb2;
|
||||
decltype(cb) cb2(cb);
|
||||
cb = cb2;
|
||||
decltype(cbc) cbc2(cbc);
|
||||
cbc = cbc2;
|
||||
}
|
||||
{
|
||||
decltype(cb) cb2(mb);
|
||||
decltype(cbc) cbc2(mb);
|
||||
cb2 = mb;
|
||||
cbc2 = mb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
/** Test an instance of a dynamic buffer or mutable dynamic buffer.
|
||||
*/
|
||||
template<class DynamicBuffer>
|
||||
void
|
||||
test_dynamic_buffer(
|
||||
unit_test::suite& test,
|
||||
DynamicBuffer const& b0)
|
||||
{
|
||||
using net::buffer_size;
|
||||
|
||||
BOOST_STATIC_ASSERT(
|
||||
net::is_dynamic_buffer<DynamicBuffer>::value);
|
||||
|
||||
BOOST_STATIC_ASSERT(
|
||||
net::is_const_buffer_sequence<typename
|
||||
DynamicBuffer::const_buffers_type>::value);
|
||||
|
||||
BOOST_STATIC_ASSERT(
|
||||
net::is_mutable_buffer_sequence<typename
|
||||
DynamicBuffer::mutable_buffers_type>::value);
|
||||
|
||||
SUITE_EXPECT(test, b0.size() == 0);
|
||||
SUITE_EXPECT(test, buffer_size(b0.data()) == 0);
|
||||
|
||||
// n == 0
|
||||
{
|
||||
DynamicBuffer b(b0);
|
||||
b.commit(1);
|
||||
SUITE_EXPECT(test, b.size() == 0);
|
||||
SUITE_EXPECT(test, buffer_size(b.prepare(0)) == 0);
|
||||
b.commit(0);
|
||||
SUITE_EXPECT(test, b.size() == 0);
|
||||
b.commit(1);
|
||||
SUITE_EXPECT(test, b.size() == 0);
|
||||
b.commit(b.max_size() + 1);
|
||||
SUITE_EXPECT(test, b.size() == 0);
|
||||
b.consume(0);
|
||||
SUITE_EXPECT(test, b.size() == 0);
|
||||
b.consume(1);
|
||||
SUITE_EXPECT(test, b.size() == 0);
|
||||
b.consume(b.max_size() + 1);
|
||||
SUITE_EXPECT(test, b.size() == 0);
|
||||
}
|
||||
|
||||
// max_size
|
||||
{
|
||||
DynamicBuffer b(b0);
|
||||
if(SUITE_EXPECT(test,
|
||||
b.max_size() + 1 > b.max_size()))
|
||||
{
|
||||
try
|
||||
{
|
||||
b.prepare(b.max_size() + 1);
|
||||
test.fail("no exception", __FILE__, __LINE__);
|
||||
}
|
||||
catch(std::length_error const&)
|
||||
{
|
||||
test.pass();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
test.fail("wrong exception", __FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char buf[13];
|
||||
unsigned char k0 = 0;
|
||||
string_view src(buf, sizeof(buf));
|
||||
if(src.size() > b0.max_size())
|
||||
src = {src.data(), b0.max_size()};
|
||||
SUITE_EXPECT(test, b0.max_size() >= src.size());
|
||||
SUITE_EXPECT(test, b0.size() == 0);
|
||||
SUITE_EXPECT(test, buffer_size(b0.data()) == 0);
|
||||
auto const make_new_src =
|
||||
[&buf, &k0, &src]
|
||||
{
|
||||
auto k = k0++;
|
||||
for(std::size_t i = 0; i < src.size(); ++i)
|
||||
buf[i] = k++;
|
||||
};
|
||||
|
||||
// readable / writable buffer sequence tests
|
||||
{
|
||||
make_new_src();
|
||||
DynamicBuffer b(b0);
|
||||
auto const& bc(b);
|
||||
auto const mb = b.prepare(src.size());
|
||||
SUITE_EXPECT(test, buffer_size(mb) == src.size());
|
||||
beast::test_buffer_sequence(test, mb);
|
||||
b.commit(net::buffer_copy(mb,
|
||||
net::const_buffer(src.data(), src.size())));
|
||||
SUITE_EXPECT(test,
|
||||
buffer_size(bc.data()) == src.size());
|
||||
beast::test_buffer_sequence(test, bc.data());
|
||||
}
|
||||
|
||||
// h = in size
|
||||
// i = prepare size
|
||||
// j = commit size
|
||||
// k = consume size
|
||||
for(std::size_t h = 1; h <= src.size(); ++h)
|
||||
{
|
||||
string_view in(src.data(), h);
|
||||
for(std::size_t i = 1; i <= in.size(); ++i) {
|
||||
for(std::size_t j = 1; j <= i + 1; ++j) {
|
||||
for(std::size_t k = 1; k <= in.size(); ++k) {
|
||||
{
|
||||
make_new_src();
|
||||
|
||||
DynamicBuffer b(b0);
|
||||
auto const& bc(b);
|
||||
net::const_buffer cb(in.data(), in.size());
|
||||
while(cb.size() > 0)
|
||||
{
|
||||
auto const mb = b.prepare(
|
||||
std::min<std::size_t>(i,
|
||||
b.max_size() - b.size()));
|
||||
auto const n = net::buffer_copy(mb,
|
||||
net::const_buffer(cb.data(),
|
||||
std::min<std::size_t>(j, cb.size())));
|
||||
b.commit(n);
|
||||
cb += n;
|
||||
}
|
||||
SUITE_EXPECT(test, b.size() == in.size());
|
||||
SUITE_EXPECT(test,
|
||||
buffer_size(bc.data()) == in.size());
|
||||
SUITE_EXPECT(test, beast::buffers_to_string(
|
||||
bc.data()) == in);
|
||||
while(b.size() > 0)
|
||||
b.consume(k);
|
||||
SUITE_EXPECT(test, buffer_size(bc.data()) == 0);
|
||||
}
|
||||
} } }
|
||||
}
|
||||
|
||||
// MutableDynamicBuffer refinement
|
||||
detail::test_mutable_dynamic_buffer(test, b0,
|
||||
is_mutable_dynamic_buffer<DynamicBuffer>{});
|
||||
}
|
||||
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
|
@ -7,186 +7,17 @@
|
||||
// Official repository: https://github.com/boostorg/beast
|
||||
//
|
||||
|
||||
#ifndef BOOST_BEAST_ALLOW_DEPRECATED
|
||||
#define BOOST_BEAST_ALLOW_DEPRECATED
|
||||
#endif
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/beast/core/buffers_adapter.hpp>
|
||||
|
||||
#include "buffer_test.hpp"
|
||||
#include <boost/beast/core/ostream.hpp>
|
||||
#include <boost/beast/core/multi_buffer.hpp>
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/streambuf.hpp>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
|
||||
class buffers_adapter_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
void testBuffersAdapter()
|
||||
{
|
||||
using net::buffer;
|
||||
using net::buffer_size;
|
||||
using net::const_buffer;
|
||||
using net::mutable_buffer;
|
||||
char buf[12];
|
||||
std::string const s = "Hello, world";
|
||||
BEAST_EXPECT(s.size() == sizeof(buf));
|
||||
for(std::size_t i = 1; i < 4; ++i) {
|
||||
for(std::size_t j = 1; j < 4; ++j) {
|
||||
for(std::size_t x = 1; x < 4; ++x) {
|
||||
for(std::size_t y = 1; y < 4; ++y) {
|
||||
for(std::size_t t = 1; t < 4; ++ t) {
|
||||
for(std::size_t u = 1; u < 4; ++ u) {
|
||||
std::size_t k = sizeof(buf) - (i + j);
|
||||
std::size_t z = sizeof(buf) - (x + y);
|
||||
std::size_t v = sizeof(buf) - (t + u);
|
||||
{
|
||||
std::memset(buf, 0, sizeof(buf));
|
||||
std::array<mutable_buffer, 3> bs{{
|
||||
mutable_buffer{&buf[0], i},
|
||||
mutable_buffer{&buf[i], j},
|
||||
mutable_buffer{&buf[i+j], k}}};
|
||||
buffers_adapter<decltype(bs)> ba(std::move(bs));
|
||||
BEAST_EXPECT(ba.max_size() == sizeof(buf));
|
||||
{
|
||||
auto d = ba.prepare(z);
|
||||
BEAST_EXPECT(buffer_size(d) == z);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(0);
|
||||
BEAST_EXPECT(buffer_size(d) == 0);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(y);
|
||||
BEAST_EXPECT(buffer_size(d) == y);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(x);
|
||||
BEAST_EXPECT(buffer_size(d) == x);
|
||||
ba.commit(buffer_copy(d, buffer(s.data(), x)));
|
||||
}
|
||||
BEAST_EXPECT(ba.size() == x);
|
||||
BEAST_EXPECT(ba.max_size() == sizeof(buf));
|
||||
BEAST_EXPECT(buffer_size(ba.data()) == ba.size());
|
||||
{
|
||||
auto d = ba.prepare(x);
|
||||
BEAST_EXPECT(buffer_size(d) == x);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(0);
|
||||
BEAST_EXPECT(buffer_size(d) == 0);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(z);
|
||||
BEAST_EXPECT(buffer_size(d) == z);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(y);
|
||||
BEAST_EXPECT(buffer_size(d) == y);
|
||||
ba.commit(buffer_copy(d, buffer(s.data()+x, y)));
|
||||
}
|
||||
ba.commit(1);
|
||||
BEAST_EXPECT(ba.size() == x + y);
|
||||
BEAST_EXPECT(ba.max_size() == sizeof(buf));
|
||||
BEAST_EXPECT(buffer_size(ba.data()) == ba.size());
|
||||
{
|
||||
auto d = ba.prepare(x);
|
||||
BEAST_EXPECT(buffer_size(d) == x);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(y);
|
||||
BEAST_EXPECT(buffer_size(d) == y);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(0);
|
||||
BEAST_EXPECT(buffer_size(d) == 0);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(z);
|
||||
BEAST_EXPECT(buffer_size(d) == z);
|
||||
ba.commit(buffer_copy(d, buffer(s.data()+x+y, z)));
|
||||
}
|
||||
ba.commit(2);
|
||||
BEAST_EXPECT(ba.size() == x + y + z);
|
||||
BEAST_EXPECT(buffer_size(ba.data()) == ba.size());
|
||||
BEAST_EXPECT(buffers_to_string(ba.data()) == s);
|
||||
ba.consume(t);
|
||||
{
|
||||
auto d = ba.prepare(0);
|
||||
BEAST_EXPECT(buffer_size(d) == 0);
|
||||
}
|
||||
BEAST_EXPECT(buffers_to_string(ba.data()) == s.substr(t, std::string::npos));
|
||||
ba.consume(u);
|
||||
BEAST_EXPECT(buffers_to_string(ba.data()) == s.substr(t + u, std::string::npos));
|
||||
ba.consume(v);
|
||||
BEAST_EXPECT(buffers_to_string(ba.data()) == "");
|
||||
ba.consume(1);
|
||||
{
|
||||
auto d = ba.prepare(0);
|
||||
BEAST_EXPECT(buffer_size(d) == 0);
|
||||
}
|
||||
try
|
||||
{
|
||||
ba.prepare(1);
|
||||
fail();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
}
|
||||
}}}}}}
|
||||
}
|
||||
void testCommit()
|
||||
{
|
||||
using net::buffer_size;
|
||||
{
|
||||
using sb_type = net::streambuf;
|
||||
sb_type b;
|
||||
buffers_adapter<
|
||||
sb_type::mutable_buffers_type> ba(b.prepare(3));
|
||||
BEAST_EXPECT(buffer_size(ba.prepare(3)) == 3);
|
||||
ba.commit(2);
|
||||
BEAST_EXPECT(buffer_size(ba.data()) == 2);
|
||||
}
|
||||
{
|
||||
using sb_type = beast::multi_buffer;
|
||||
sb_type b;
|
||||
b.prepare(3);
|
||||
buffers_adapter<
|
||||
sb_type::mutable_buffers_type> ba(b.prepare(8));
|
||||
BEAST_EXPECT(buffer_size(ba.prepare(8)) == 8);
|
||||
ba.commit(2);
|
||||
BEAST_EXPECT(buffer_size(ba.data()) == 2);
|
||||
ba.consume(1);
|
||||
ba.commit(6);
|
||||
ba.consume(2);
|
||||
BEAST_EXPECT(buffer_size(ba.data()) == 5);
|
||||
ba.consume(5);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testIssue386()
|
||||
{
|
||||
using type = net::streambuf;
|
||||
type buffer;
|
||||
buffers_adapter<
|
||||
type::mutable_buffers_type> ba{buffer.prepare(512)};
|
||||
read_size(ba, 1024);
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testBuffersAdapter();
|
||||
testCommit();
|
||||
testIssue386();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,core,buffers_adapter);
|
||||
BOOST_STATIC_ASSERT(sizeof(buffers_adapter<net::mutable_buffer>) > 0);
|
||||
|
||||
} // beast
|
||||
} // boost
|
||||
|
104
test/beast/core/buffers_adaptor.cpp
Normal file
104
test/beast/core/buffers_adaptor.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
//
|
||||
// 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
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/beast/core/buffers_adaptor.hpp>
|
||||
|
||||
#include "buffer_test.hpp"
|
||||
|
||||
#include <boost/beast/core/multi_buffer.hpp>
|
||||
#include <boost/beast/core/ostream.hpp>
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/streambuf.hpp>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
|
||||
class buffers_adaptor_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_ASSERT(
|
||||
is_mutable_dynamic_buffer<
|
||||
buffers_adaptor<buffers_triple>>::value);
|
||||
|
||||
void
|
||||
testDynamicBuffer()
|
||||
{
|
||||
char s[13];
|
||||
buffers_triple tb(s, sizeof(s));
|
||||
buffers_adaptor<buffers_triple> b(tb);
|
||||
test_dynamic_buffer(*this, b);
|
||||
}
|
||||
|
||||
void
|
||||
testSpecial()
|
||||
{
|
||||
using net::buffer_size;
|
||||
|
||||
char s1[13];
|
||||
buffers_triple tb1(s1, sizeof(s1));
|
||||
BEAST_EXPECT(buffer_size(tb1) == sizeof(s1));
|
||||
|
||||
char s2[15];
|
||||
buffers_triple tb2(s2, sizeof(s2));
|
||||
BEAST_EXPECT(buffer_size(tb2) == sizeof(s2));
|
||||
|
||||
{
|
||||
// construction
|
||||
|
||||
buffers_adaptor<buffers_triple> b1(tb1);
|
||||
BEAST_EXPECT(b1.value() == tb1);
|
||||
|
||||
buffers_adaptor<buffers_triple> b2(tb2);
|
||||
BEAST_EXPECT(b2.value() == tb2);
|
||||
|
||||
buffers_adaptor<buffers_triple> b3(b2);
|
||||
BEAST_EXPECT(b3.value() == tb2);
|
||||
|
||||
char s3[15];
|
||||
buffers_adaptor<buffers_triple> b4(
|
||||
boost::in_place_init, s3, sizeof(s3));
|
||||
BEAST_EXPECT(b4.value() == buffers_triple(s3, sizeof(s3)));
|
||||
|
||||
// assignment
|
||||
|
||||
b3 = b1;
|
||||
BEAST_EXPECT(b3.value() == tb1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testIssue386()
|
||||
{
|
||||
using type = net::streambuf;
|
||||
type buffer;
|
||||
buffers_adaptor<
|
||||
type::mutable_buffers_type> ba{buffer.prepare(512)};
|
||||
read_size(ba, 1024);
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
testDynamicBuffer();
|
||||
testSpecial();
|
||||
testIssue386();
|
||||
#if 0
|
||||
testBuffersAdapter();
|
||||
testCommit();
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,core,buffers_adaptor);
|
||||
|
||||
} // beast
|
||||
} // boost
|
@ -10,7 +10,7 @@
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/beast/_experimental/http/icy_stream.hpp>
|
||||
|
||||
#include <boost/beast/core/buffers_adapter.hpp>
|
||||
#include <boost/beast/core/buffers_adaptor.hpp>
|
||||
#include <boost/beast/core/buffers_to_string.hpp>
|
||||
#include <boost/beast/core/read_size.hpp>
|
||||
#include <boost/beast/_experimental/test/stream.hpp>
|
||||
@ -45,7 +45,7 @@ public:
|
||||
{
|
||||
// sync
|
||||
{
|
||||
buffers_adapter<decltype(mbs)> ba(mbs);
|
||||
buffers_adaptor<decltype(mbs)> ba(mbs);
|
||||
std::memset(p.get(), 0, len);
|
||||
|
||||
icy_stream<test::stream> is{ioc};
|
||||
@ -69,7 +69,7 @@ public:
|
||||
}
|
||||
// async
|
||||
{
|
||||
buffers_adapter<decltype(mbs)> ba(mbs);
|
||||
buffers_adaptor<decltype(mbs)> ba(mbs);
|
||||
std::memset(p.get(), 0, len);
|
||||
|
||||
icy_stream<test::stream> is{ioc};
|
||||
|
Reference in New Issue
Block a user