Add drain_buffer class

fix #457
This commit is contained in:
Vinnie Falco
2017-06-09 17:52:00 -07:00
parent 23863230de
commit 5149cf8495
7 changed files with 185 additions and 0 deletions

View File

@ -1,6 +1,7 @@
Version 52:
* flat_buffer is an AllocatorAwareContainer
* Add drain_buffer class
API Changes:

View File

@ -47,6 +47,15 @@ To suit various needs, several implementation of dynamic buffer are available:
output areas equal to the size of the underlying mutable buffer sequence.
The implementation does not perform heap allocations.
]]
[[
[link beast.ref.drain_buffer `drain_buffer`]
][
A drain buffer has a small internal buffer and maximum size that
uses no dynamic allocation. It always has a size of zero, and
silently discards its input. This buffer may be passed to functions
which store data in a dynamic buffer when the caller wishes to
efficiently discard the data.
]]
[[
[link beast.ref.flat_buffer `flat_buffer`]
[link beast.ref.basic_flat_buffer `basic_flat_buffer`]

View File

@ -165,6 +165,7 @@
<member><link linkend="beast.ref.buffered_read_stream">buffered_read_stream</link></member>
<member><link linkend="beast.ref.buffers_adapter">buffers_adapter</link></member>
<member><link linkend="beast.ref.consuming_buffers">consuming_buffers</link></member>
<member><link linkend="beast.ref.drain_buffer">drain_buffer</link></member>
<member><link linkend="beast.ref.error_category">error_category</link></member>
<member><link linkend="beast.ref.error_code">error_code</link></member>
<member><link linkend="beast.ref.error_condition">error_condition</link></member>

View File

@ -0,0 +1,121 @@
//
// Copyright (c) 2013-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)
//
#ifndef BEAST_DRAIN_BUFFER_HPP
#define BEAST_DRAIN_BUFFER_HPP
#include <beast/config.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/throw_exception.hpp>
namespace beast {
/** A @b DynamicBuffer which does not retain its input sequence.
This object implements a dynamic buffer with a fixed size
output area, not dynamically allocated, and whose input
sequence is always length zero. Bytes committed from the
output area to the input area are always discarded. This
is useful for calling interfaces that require a dynamic
buffer for storage, but where the caller does not want
to retain the data.
*/
class drain_buffer
{
char buf_[512];
std::size_t n_ = 0;
public:
/// The type used to represent the input sequence as a list of buffers.
using const_buffers_type = boost::asio::null_buffers;
/// The type used to represent the output sequence as a list of buffers.
using mutable_buffers_type = boost::asio::mutable_buffers_1;
/// Constructor
drain_buffer() = default;
/// Copy constructor
drain_buffer(drain_buffer const&)
{
}
/// Copy assignment
drain_buffer&
operator=(drain_buffer const&)
{
n_ = 0;
return *this;
}
/// Return the size of the input sequence.
std::size_t
size() const
{
return 0;
}
/// Return the maximum sum of the input and output sequence sizes.
std::size_t
max_size() const
{
return sizeof(buf_);
}
/// Return the maximum sum of input and output sizes that can be held without an allocation.
std::size_t
capacity() const
{
return max_size();
}
/** Get a list of buffers that represent the input sequence.
@note These buffers remain valid across subsequent calls to `prepare`.
*/
const_buffers_type
data() const
{
return {};
}
/** Get a list of buffers that represent the output sequence, with the given size.
@throws std::length_error if the size would exceed the buffer limit
*/
mutable_buffers_type
prepare(std::size_t n)
{
if(n > sizeof(buf_))
BOOST_THROW_EXCEPTION(std::length_error{
"buffer overflow"});
n_ = n;
return {buf_, n_};
}
/** Move bytes from the output sequence to the input sequence.
This call always discards the output sequence.
The size of the input sequence will remain at zero.
*/
void
commit(std::size_t)
{
}
/** Remove bytes from the input sequence.
This call has no effect.
*/
void
consume(std::size_t) const
{
}
};
} // beast
#endif

View File

@ -27,6 +27,7 @@ unit-test core-tests :
core/consuming_buffers.cpp
core/doc_core_samples.cpp
core/doc_snippets.cpp
core/drain_buffer.cpp
core/error.cpp
core/flat_buffer.cpp
core/handler_alloc.cpp

View File

@ -22,6 +22,7 @@ add_executable (core-tests
consuming_buffers.cpp
doc_core_samples.cpp
doc_snippets.cpp
drain_buffer.cpp
error.cpp
flat_buffer.cpp
handler_alloc.cpp

View File

@ -0,0 +1,51 @@
//
// Copyright (c) 2013-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)
//
// Test that header file is self-contained.
#include <beast/core/drain_buffer.hpp>
#include <beast/core/type_traits.hpp>
#include <beast/unit_test/suite.hpp>
namespace beast {
static_assert(is_dynamic_buffer<drain_buffer>::value,
"DynamicBuffer requirements not met");
class drain_buffer_test : public beast::unit_test::suite
{
public:
void
run() override
{
using boost::asio::buffer_size;
drain_buffer b;
BEAST_EXPECT(buffer_size(b.prepare(0)) == 0);
BEAST_EXPECT(buffer_size(b.prepare(100)) == 100);
try
{
b.prepare(b.max_size() + 1);
fail("", __FILE__, __LINE__);
}
catch(std::length_error const&)
{
pass();
}
b.prepare(10);
BEAST_EXPECT(b.size() == 0);
b.commit(10);
BEAST_EXPECT(b.size() == 0);
b.consume(10);
BEAST_EXPECT(b.size() == 0);
b.consume(1000);
BEAST_EXPECT(b.size() == 0);
}
};
BEAST_DEFINE_TESTSUITE(drain_buffer,core,beast);
} // beast