mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 12:57:31 +02:00
buffer_ref allows using beast buffers with asio.
This commit is contained in:
committed by
Klemens Morgenstern
parent
606d776ebb
commit
9d680df683
@ -96,6 +96,16 @@ transferred.
|
|||||||
This function converts a buffer sequence to a `std::string`. It can
|
This function converts a buffer sequence to a `std::string`. It can
|
||||||
be used for diagnostic purposes and tests.
|
be used for diagnostic purposes and tests.
|
||||||
]]
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.boost__beast__buffer_ref `buffer_ref`]
|
||||||
|
[link beast.ref.boost__beast__ref `ref`]
|
||||||
|
|
||||||
|
][
|
||||||
|
This function converts a beast buffer, that is to be passed by reference,
|
||||||
|
into a buffer reference, that can be passed by value into asio functions.
|
||||||
|
|
||||||
|
It implements the __DynamicBuffer__v2__ concept.
|
||||||
|
]]
|
||||||
]
|
]
|
||||||
|
|
||||||
The __DynamicBuffer__ concept introduced in __Asio__ models a buffer
|
The __DynamicBuffer__ concept introduced in __Asio__ models a buffer
|
||||||
|
@ -87,6 +87,8 @@
|
|||||||
[def __SyncReadStream__ [@boost:/doc/html/boost_asio/reference/SyncReadStream.html ['SyncReadStream]]]
|
[def __SyncReadStream__ [@boost:/doc/html/boost_asio/reference/SyncReadStream.html ['SyncReadStream]]]
|
||||||
[def __SyncWriteStream__ [@boost:/doc/html/boost_asio/reference/SyncWriteStream.html ['SyncWriteStream]]]
|
[def __SyncWriteStream__ [@boost:/doc/html/boost_asio/reference/SyncWriteStream.html ['SyncWriteStream]]]
|
||||||
[def __WriteHandler__ [@boost:/doc/html/boost_asio/reference/WriteHandler.html ['WriteHandler]]]
|
[def __WriteHandler__ [@boost:/doc/html/boost_asio/reference/WriteHandler.html ['WriteHandler]]]
|
||||||
|
[def __DynamicBuffer__v1__ [@boost:/doc/html/boost_asio/reference/DynamicBuffer_v1.html ['DynamicBuffer_v1']]]
|
||||||
|
[def __DynamicBuffer__v2__ [@boost:/doc/html/boost_asio/reference/DynamicBuffer_v2.html ['DynamicBuffer_v2']]]
|
||||||
|
|
||||||
[/ Beast Named Requirements ]
|
[/ Beast Named Requirements ]
|
||||||
|
|
||||||
|
@ -125,6 +125,7 @@
|
|||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.boost__beast__basic_flat_buffer">basic_flat_buffer</link></member>
|
<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__basic_multi_buffer">basic_multi_buffer</link></member>
|
||||||
|
<member><link linkend="beast.ref.boost__beast__buffer_ref">buffer_ref</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__buffered_read_stream">buffered_read_stream</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_adaptor">buffers_adaptor</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_cat_view">buffers_cat_view</link></member>
|
||||||
@ -152,6 +153,7 @@
|
|||||||
<member><link linkend="beast.ref.boost__beast__ostream">ostream</link></member>
|
<member><link linkend="beast.ref.boost__beast__ostream">ostream</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__read_size">read_size</link></member>
|
<member><link linkend="beast.ref.boost__beast__read_size">read_size</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__read_size_or_throw">read_size_or_throw</link></member>
|
<member><link linkend="beast.ref.boost__beast__read_size_or_throw">read_size_or_throw</link></member>
|
||||||
|
<member><link linkend="beast.ref.boost__beast__ref">ref</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__write">write</link></member>
|
<member><link linkend="beast.ref.boost__beast__write">write</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
</entry><entry valign="top">
|
</entry><entry valign="top">
|
||||||
|
177
include/boost/beast/core/buffer_ref.hpp
Normal file
177
include/boost/beast/core/buffer_ref.hpp
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||||
|
//
|
||||||
|
// 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)
|
||||||
|
#ifndef BOOST_BEAST_BUFFER_REF_HPP
|
||||||
|
#define BOOST_BEAST_BUFFER_REF_HPP
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
|
||||||
|
#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
|
||||||
|
|
||||||
|
/** The buffer ref provides a wrapper around beast buffers
|
||||||
|
* to make them usable with asio dynamic_buffer v1.
|
||||||
|
*
|
||||||
|
* v2 is current not supported, so that
|
||||||
|
* `BOOST_ASIO_NO_DYNAMIC_BUFFER_V1` mustn't be defined.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
*
|
||||||
|
* asio::tcp::socket sock;
|
||||||
|
* beast::flat_buffer fb;
|
||||||
|
* asio::read_until(sock, ref(fb) '\n');
|
||||||
|
*
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @tparam Buffer The underlying buffer
|
||||||
|
*/
|
||||||
|
template<typename Buffer>
|
||||||
|
struct buffer_ref
|
||||||
|
{
|
||||||
|
/// The ConstBufferSequence used to represent the readable bytes.
|
||||||
|
using const_buffers_type = typename Buffer::const_buffers_type;
|
||||||
|
|
||||||
|
/// The MutableBufferSequence used to represent the writable bytes.
|
||||||
|
using mutable_buffers_type = typename Buffer::mutable_buffers_type;
|
||||||
|
|
||||||
|
/// Returns the number of readable bytes.
|
||||||
|
std::size_t
|
||||||
|
size() const noexcept
|
||||||
|
{
|
||||||
|
return buffer_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the maximum number of bytes, both readable and writable, that can ever be held.
|
||||||
|
std::size_t
|
||||||
|
max_size() const noexcept
|
||||||
|
{
|
||||||
|
return buffer_.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 buffer_.capacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a constant buffer sequence representing the readable bytes
|
||||||
|
const_buffers_type
|
||||||
|
data() const noexcept
|
||||||
|
{
|
||||||
|
return buffer_.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a list of buffers that represents the output
|
||||||
|
/// sequence, with the given size.
|
||||||
|
/**
|
||||||
|
* Ensures that the output sequence can accommodate @c n bytes, resizing the
|
||||||
|
* vector object as necessary.
|
||||||
|
*
|
||||||
|
* @returns An object of type @c mutable_buffers_type that satisfies
|
||||||
|
* MutableBufferSequence requirements, representing vector memory at the
|
||||||
|
* start of the output sequence of size @c n.
|
||||||
|
*
|
||||||
|
* @throws std::length_error If <tt>size() + n > max_size()</tt>.
|
||||||
|
*
|
||||||
|
* @note The returned object is invalidated by any @c dynamic_vector_buffer
|
||||||
|
* or @c vector member function that modifies the input sequence or output
|
||||||
|
* sequence.
|
||||||
|
*/
|
||||||
|
mutable_buffers_type prepare(std::size_t n)
|
||||||
|
{
|
||||||
|
return buffer_.prepare(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move bytes from the output sequence to the input
|
||||||
|
/// sequence.
|
||||||
|
/**
|
||||||
|
* @param n The number of bytes to append from the start of the output
|
||||||
|
* sequence to the end of the input sequence. The remainder of the output
|
||||||
|
* sequence is discarded.
|
||||||
|
*
|
||||||
|
* Requires a preceding call <tt>prepare(x)</tt> where <tt>x >= n</tt>, and
|
||||||
|
* no intervening operations that modify the input or output sequence.
|
||||||
|
*
|
||||||
|
* @note If @c n is greater than the size of the output sequence, the entire
|
||||||
|
* output sequence is moved to the input sequence and no error is issued.
|
||||||
|
*/
|
||||||
|
void commit(std::size_t n)
|
||||||
|
{
|
||||||
|
return buffer_.commit(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove `n` bytes from the readable byte sequence.
|
||||||
|
/**
|
||||||
|
* @b DynamicBuffer_v1: Removes @c n characters from the beginning of the
|
||||||
|
* input sequence. @note If @c n is greater than the size of the input
|
||||||
|
* sequence, the entire input sequence is consumed and no error is issued.
|
||||||
|
*/
|
||||||
|
void consume(std::size_t n)
|
||||||
|
{
|
||||||
|
return buffer_.consume(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The type of the underlying buffer.
|
||||||
|
using buffer_type = Buffer;
|
||||||
|
|
||||||
|
/// Create a buffer reference around @c buffer.
|
||||||
|
buffer_ref(Buffer & buffer) : buffer_(buffer) {}
|
||||||
|
|
||||||
|
/// Copy the reference.
|
||||||
|
buffer_ref(const buffer_ref& buffer) = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Buffer &buffer_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<class Allocator>
|
||||||
|
class basic_flat_buffer;
|
||||||
|
template<std::size_t N>
|
||||||
|
class flat_static_buffer;
|
||||||
|
template<class Allocator>
|
||||||
|
class basic_multi_buffer;
|
||||||
|
template<std::size_t N>
|
||||||
|
class static_buffer;
|
||||||
|
|
||||||
|
/// Create a buffer_ref for basic_flat_buffer.
|
||||||
|
template<class Allocator>
|
||||||
|
inline buffer_ref<basic_flat_buffer<Allocator>> ref(basic_flat_buffer<Allocator> & buf)
|
||||||
|
{
|
||||||
|
return buffer_ref<basic_flat_buffer<Allocator>>(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a buffer_ref for flat_static_buffer.
|
||||||
|
template<std::size_t N>
|
||||||
|
inline buffer_ref<flat_static_buffer<N>> ref(flat_static_buffer<N> & buf)
|
||||||
|
{
|
||||||
|
return buffer_ref<flat_static_buffer<N>>(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a buffer_ref for basic_multi_buffer.
|
||||||
|
template<class Allocator>
|
||||||
|
inline buffer_ref<basic_multi_buffer<Allocator>> ref(basic_multi_buffer<Allocator> & buf)
|
||||||
|
{
|
||||||
|
return buffer_ref<basic_multi_buffer<Allocator>>(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a buffer_ref for static_buffer.
|
||||||
|
template<std::size_t N>
|
||||||
|
inline buffer_ref<static_buffer<N>> ref(static_buffer<N> & buf)
|
||||||
|
{
|
||||||
|
return buffer_ref<static_buffer<N>>(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //BOOST_BEAST_BUFFER_REF_HPP
|
@ -31,6 +31,7 @@ add_executable (tests-beast-core
|
|||||||
async_base.cpp
|
async_base.cpp
|
||||||
basic_stream.cpp
|
basic_stream.cpp
|
||||||
bind_handler.cpp
|
bind_handler.cpp
|
||||||
|
buffer_ref.cpp
|
||||||
buffer_traits.cpp
|
buffer_traits.cpp
|
||||||
buffered_read_stream.cpp
|
buffered_read_stream.cpp
|
||||||
buffers_adaptor.cpp
|
buffers_adaptor.cpp
|
||||||
|
@ -22,6 +22,7 @@ local SOURCES =
|
|||||||
async_base.cpp
|
async_base.cpp
|
||||||
basic_stream.cpp
|
basic_stream.cpp
|
||||||
bind_handler.cpp
|
bind_handler.cpp
|
||||||
|
buffer_ref.cpp
|
||||||
buffer_traits.cpp
|
buffer_traits.cpp
|
||||||
buffered_read_stream.cpp
|
buffered_read_stream.cpp
|
||||||
buffers_adaptor.cpp
|
buffers_adaptor.cpp
|
||||||
|
87
test/beast/core/buffer_ref.cpp
Normal file
87
test/beast/core/buffer_ref.cpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// Copyright (c) 2022 Klemens D. Morgenstern
|
||||||
|
//
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
#include <boost/beast/core/buffer_ref.hpp>
|
||||||
|
#include <boost/beast/core/flat_buffer.hpp>
|
||||||
|
#include <boost/beast/core/flat_static_buffer.hpp>
|
||||||
|
#include <boost/beast/core/multi_buffer.hpp>
|
||||||
|
#include <boost/beast/core/static_buffer.hpp>
|
||||||
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
|
#include <boost/asio/io_context.hpp>
|
||||||
|
#include <boost/asio/readable_pipe.hpp>
|
||||||
|
#include <boost/asio/writable_pipe.hpp>
|
||||||
|
#include <boost/asio/connect_pipe.hpp>
|
||||||
|
#include <boost/asio/write.hpp>
|
||||||
|
#include <boost/asio/detached.hpp>
|
||||||
|
#include <boost/asio/read_until.hpp>
|
||||||
|
#include "test_buffer.hpp"
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
|
||||||
|
template struct buffer_ref<flat_buffer>;
|
||||||
|
template struct buffer_ref<flat_static_buffer<2u>>;
|
||||||
|
template struct buffer_ref<multi_buffer>;
|
||||||
|
template struct buffer_ref<static_buffer<2u>>;
|
||||||
|
|
||||||
|
class buffer_ref_test : public beast::unit_test::suite
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename Buffer>
|
||||||
|
void testBuffer()
|
||||||
|
{
|
||||||
|
net::io_context ioc;
|
||||||
|
net::readable_pipe rp{ioc};
|
||||||
|
net::writable_pipe wp{ioc};
|
||||||
|
net::connect_pipe(rp, wp);
|
||||||
|
|
||||||
|
const char msg[] = "Hello, world!\n";
|
||||||
|
|
||||||
|
net::async_write(wp, net::buffer(msg), asio::detached);
|
||||||
|
|
||||||
|
Buffer buf;
|
||||||
|
|
||||||
|
net::async_read_until(rp, ref(buf), '\n', asio::detached);
|
||||||
|
ioc.run();
|
||||||
|
// writable, not commited yet!
|
||||||
|
std::string cmp;
|
||||||
|
cmp.resize(sizeof(msg) -1);
|
||||||
|
const auto n = net::buffer_copy(net::buffer(cmp), buf.data());
|
||||||
|
BEAST_EXPECT(n >= std::strlen(msg));
|
||||||
|
cmp.resize(13);
|
||||||
|
BEAST_EXPECT(cmp == "Hello, world!");
|
||||||
|
|
||||||
|
|
||||||
|
buf = Buffer();
|
||||||
|
test_dynamic_buffer_ref(ref(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
run() override
|
||||||
|
{
|
||||||
|
testBuffer<flat_buffer>();
|
||||||
|
testBuffer<flat_static_buffer<1024u>>();
|
||||||
|
testBuffer<multi_buffer>();
|
||||||
|
testBuffer<static_buffer<1024u>>();
|
||||||
|
|
||||||
|
{
|
||||||
|
std::string buf;
|
||||||
|
test_dynamic_buffer_ref(asio::dynamic_buffer(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::vector<unsigned char> buf;
|
||||||
|
test_dynamic_buffer_ref(asio::dynamic_buffer(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE(beast,core, buffer_ref);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -593,6 +593,184 @@ test_dynamic_buffer(
|
|||||||
is_mutable_dynamic_buffer<DynamicBuffer_v0>{});
|
is_mutable_dynamic_buffer<DynamicBuffer_v0>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Test an instance of a dynamic buffer or mutable dynamic buffer.
|
||||||
|
*/
|
||||||
|
template<class DynamicBuffer_v0>
|
||||||
|
void
|
||||||
|
test_dynamic_buffer_ref(DynamicBuffer_v0 b0)
|
||||||
|
{
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
net::is_dynamic_buffer_v1<DynamicBuffer_v0>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
net::is_const_buffer_sequence<typename
|
||||||
|
DynamicBuffer_v0::const_buffers_type>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
net::is_mutable_buffer_sequence<typename
|
||||||
|
DynamicBuffer_v0::mutable_buffers_type>::value);
|
||||||
|
|
||||||
|
BEAST_EXPECT(b0.size() == 0);
|
||||||
|
BEAST_EXPECT(buffer_bytes(b0.data()) == 0);
|
||||||
|
|
||||||
|
// members
|
||||||
|
{
|
||||||
|
string_view src = "Hello, world!";
|
||||||
|
|
||||||
|
DynamicBuffer_v0 b1(b0);
|
||||||
|
auto const mb = b1.prepare(src.size());
|
||||||
|
b1.commit(net::buffer_copy(mb,
|
||||||
|
net::const_buffer(src.data(), src.size())));
|
||||||
|
|
||||||
|
// copy constructor
|
||||||
|
{
|
||||||
|
DynamicBuffer_v0 b2(b1);
|
||||||
|
BEAST_EXPECT(b2.size() == b1.size());
|
||||||
|
BEAST_EXPECT(
|
||||||
|
buffers_to_string(b1.data()) ==
|
||||||
|
buffers_to_string(b2.data()));
|
||||||
|
|
||||||
|
// https://github.com/boostorg/beast/issues/1621
|
||||||
|
b2.consume(1);
|
||||||
|
BEAST_EXPECT(b0.size() == b2.size());
|
||||||
|
BEAST_EXPECT(
|
||||||
|
buffers_to_string(b2.data()) ==
|
||||||
|
buffers_to_string(b0.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// move constructor
|
||||||
|
{
|
||||||
|
DynamicBuffer_v0 b2(b1);
|
||||||
|
DynamicBuffer_v0 b3(std::move(b2));
|
||||||
|
BEAST_EXPECT(b3.size() == b1.size());
|
||||||
|
BEAST_EXPECT(
|
||||||
|
buffers_to_string(b3.data()) ==
|
||||||
|
buffers_to_string(b1.data()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// n == 0
|
||||||
|
{
|
||||||
|
|
||||||
|
DynamicBuffer_v0 b(b0);
|
||||||
|
|
||||||
|
const std::size_t len = b0.size();
|
||||||
|
BEAST_EXPECT(b.size() == len);
|
||||||
|
BEAST_EXPECT(buffer_bytes(b.prepare(0)) == 0);
|
||||||
|
b.commit(0);
|
||||||
|
BEAST_EXPECT(b.size() == len);
|
||||||
|
b.commit(1);
|
||||||
|
BEAST_EXPECT(b.size() == len);
|
||||||
|
b.commit(b.max_size() + 1);
|
||||||
|
BEAST_EXPECT(b.size() == len);
|
||||||
|
b.consume(0);
|
||||||
|
BEAST_EXPECT(b.size() == len);
|
||||||
|
b.consume(1);
|
||||||
|
BEAST_EXPECT(b.size() == len - 1);
|
||||||
|
b.consume(len - 1);
|
||||||
|
BEAST_EXPECTS(b.size() == 0, typeid(b).name());
|
||||||
|
}
|
||||||
|
|
||||||
|
// max_size
|
||||||
|
{
|
||||||
|
DynamicBuffer_v0 b(b0);
|
||||||
|
if(b.max_size() + 1 > b.max_size())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
b.prepare(b.max_size() + 1);
|
||||||
|
BEAST_FAIL();
|
||||||
|
}
|
||||||
|
catch(std::length_error const&)
|
||||||
|
{
|
||||||
|
BEAST_PASS();
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
BEAST_FAIL();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
BEAST_EXPECT(b.max_size() == std::numeric_limits<std::size_t>::max());
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup source buffer
|
||||||
|
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()};
|
||||||
|
BEAST_EXPECT(b0.max_size() >= src.size());
|
||||||
|
BEAST_EXPECT(b0.size() == 0);
|
||||||
|
BEAST_EXPECT(buffer_bytes(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_v0 b(b0);
|
||||||
|
auto const& bc(b);
|
||||||
|
auto const mb = b.prepare(src.size());
|
||||||
|
BEAST_EXPECT(buffer_bytes(mb) == src.size());
|
||||||
|
beast::test_buffer_sequence(mb);
|
||||||
|
b.commit(net::buffer_copy(mb,
|
||||||
|
net::const_buffer(src.data(), src.size())));
|
||||||
|
BEAST_EXPECT(
|
||||||
|
buffer_bytes(bc.data()) == src.size());
|
||||||
|
beast::test_buffer_sequence(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();
|
||||||
|
|
||||||
|
const std::size_t len = b0.size();
|
||||||
|
DynamicBuffer_v0 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;
|
||||||
|
}
|
||||||
|
BEAST_EXPECT(b.size() == (in.size() + len));
|
||||||
|
BEAST_EXPECT(buffer_bytes(bc.data()) == in.size() + len);
|
||||||
|
BEAST_EXPECT(beast::buffers_to_string(bc.data()).substr(len) == in);
|
||||||
|
while(b.size() > 0)
|
||||||
|
b.consume(k);
|
||||||
|
BEAST_EXPECT(buffer_bytes(bc.data()) == 0);
|
||||||
|
}
|
||||||
|
} } }
|
||||||
|
}
|
||||||
|
|
||||||
|
// MutableDynamicBuffer_v0 refinement
|
||||||
|
detail::test_mutable_dynamic_buffer(b0,
|
||||||
|
is_mutable_dynamic_buffer<DynamicBuffer_v0>{});
|
||||||
|
}
|
||||||
|
|
||||||
} // beast
|
} // beast
|
||||||
} // boost
|
} // boost
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user