Add dynamic_buffer_ref

This commit is contained in:
Vinnie Falco
2019-02-02 16:14:10 -08:00
parent bfb500110b
commit 17ada67f0d
10 changed files with 211 additions and 104 deletions

View File

@@ -4,6 +4,7 @@ Version 209:
* async_echo supports move-only handlers
* test::stream maintains a handler work guard
* Qualify buffer_copy, don't qualify buffer_size
* Add dynamic_buffer_ref
--------------------------------------------------------------------------------

View File

@@ -125,6 +125,15 @@ set of additional implementations of the dynamic buffer concept:
The basic container is an
[@https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer [*AllocatorAwareContainer]].
]]
[[
[link beast.ref.boost__beast__dynamic_buffer_ref `dynamic_buffer_ref`]
[link beast.ref.boost__beast__dynamic_buffer_ref_wrapper `dynamic_buffer_ref_wrapper`]
][
This function returns a wrapper containing a reference to the passed
dynamic buffer, permitting a Beast dynamic buffer type (which acts
like a true container type) to be used with Networking algorithms
which want to take ownership of the dynamic buffer in their interface.
]]
[[
[link beast.ref.boost__beast__flat_static_buffer `flat_static_buffer`]
[link beast.ref.boost__beast__flat_static_buffer_base `flat_static_buffer_base`]

View File

@@ -186,6 +186,7 @@
<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>
<member><link linkend="beast.ref.boost__beast__dynamic_buffer_ref_wrapper">dynamic_buffer_ref_wrapper</link></member>
<member><link linkend="beast.ref.boost__beast__file">file</link></member>
<member><link linkend="beast.ref.boost__beast__file_mode">file_mode</link></member>
<member><link linkend="beast.ref.boost__beast__file_posix">file_posix</link></member>
@@ -236,6 +237,7 @@
<member><link linkend="beast.ref.boost__beast__buffers_range_ref">buffers_range_ref</link></member>
<member><link linkend="beast.ref.boost__beast__buffers_to_string">buffers_to_string</link></member>
<member><link linkend="beast.ref.boost__beast__close_socket">close_socket</link></member>
<member><link linkend="beast.ref.boost__beast__dynamic_buffer_ref">dynamic_buffer_ref</link></member>
<member><link linkend="beast.ref.boost__beast__generic_category">generic_category</link></member>
<member><link linkend="beast.ref.boost__beast__get_lowest_layer">get_lowest_layer</link></member>
<member><link linkend="beast.ref.boost__beast__iequals">iequals</link></member>

View File

@@ -1,99 +0,0 @@
//
// Copyright (c) 2018 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_CORE_DETAIL_DYNAMIC_BUFFER_REF_HPP
#define BOOST_BEAST_CORE_DETAIL_DYNAMIC_BUFFER_REF_HPP
#include <boost/asio/buffer.hpp>
#include <cstdlib>
#include <type_traits>
namespace boost {
namespace beast {
namespace detail {
template<class DynamicBuffer>
class dynamic_buffer_ref
{
DynamicBuffer& b_;
public:
using const_buffers_type = typename
DynamicBuffer::const_buffers_type;
using mutable_buffers_type = typename
DynamicBuffer::mutable_buffers_type;
dynamic_buffer_ref(
dynamic_buffer_ref&&) = default;
explicit
dynamic_buffer_ref(
DynamicBuffer& b) noexcept
: b_(b)
{
}
std::size_t
size() const noexcept
{
return b_.size();
}
std::size_t
max_size() const noexcept
{
return b_.max_size();
}
std::size_t
capacity() const noexcept
{
return b_.capacity();
}
const_buffers_type
data() const noexcept
{
return b_.data();
}
mutable_buffers_type
prepare(std::size_t n)
{
return b_.prepare(n);
}
void
commit(std::size_t n)
{
b_.commit(n);
}
void
consume(std::size_t n)
{
b_.consume(n);
}
};
template<class DynamicBuffer>
typename std::enable_if<
net::is_dynamic_buffer<DynamicBuffer>::value,
dynamic_buffer_ref<DynamicBuffer>>::type
ref(DynamicBuffer& b)
{
return dynamic_buffer_ref<DynamicBuffer>(b);
}
} // detail
} // beast
} // boost
#endif

View File

@@ -10,7 +10,7 @@
#ifndef BOOST_BEAST_CORE_IMPL_ICY_STREAM_HPP
#define BOOST_BEAST_CORE_IMPL_ICY_STREAM_HPP
#include <boost/beast/_experimental/core/detail/dynamic_buffer_ref.hpp>
#include <boost/beast/core/dynamic_buffer_ref.hpp>
#include <boost/beast/core/async_op_base.hpp>
#include <boost/beast/core/bind_handler.hpp>
#include <boost/beast/core/buffers_adaptor.hpp>
@@ -164,7 +164,7 @@ public:
std::size_t bytes_transferred)
{
using iterator = net::buffers_iterator<
typename beast::detail::dynamic_buffer_ref<
typename beast::dynamic_buffer_ref_wrapper<
buffers_adaptor<MutableBufferSequence>>::const_buffers_type>;
BOOST_ASIO_CORO_REENTER(*this)
{
@@ -250,7 +250,7 @@ public:
BOOST_ASIO_CORO_YIELD
net::async_read_until(
d_.s.next_layer(),
beast::detail::ref(d_.b),
beast::dynamic_buffer_ref(d_.b),
detail::match_icy<iterator>(d_.match),
std::move(*this));
if(ec)
@@ -329,7 +329,7 @@ read_some(MutableBufferSequence const& buffers, error_code& ec)
MutableBufferSequence>::value,
"MutableBufferSequence requirements not met");
using iterator = net::buffers_iterator<
typename beast::detail::dynamic_buffer_ref<
typename beast::dynamic_buffer_ref_wrapper<
buffers_adaptor<MutableBufferSequence>>::const_buffers_type>;
buffers_adaptor<MutableBufferSequence> b(buffers);
if(b.max_size() == 0)
@@ -403,7 +403,7 @@ read_some(MutableBufferSequence const& buffers, error_code& ec)
bool match = false;
auto n = net::read_until(
stream_,
beast::detail::ref(b),
beast::dynamic_buffer_ref(b),
detail::match_icy<iterator>(match),
ec);
if(ec)

View File

@@ -23,6 +23,7 @@
#include <boost/beast/core/buffers_suffix.hpp>
#include <boost/beast/core/buffers_to_string.hpp>
#include <boost/beast/core/close_socket.hpp>
#include <boost/beast/core/dynamic_buffer_ref.hpp>
#include <boost/beast/core/error.hpp>
#include <boost/beast/core/file.hpp>
#include <boost/beast/core/file_base.hpp>

View File

@@ -0,0 +1,140 @@
//
// Copyright (c) 2018 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_CORE_DYNAMIC_BUFFER_REF_HPP
#define BOOST_BEAST_CORE_DYNAMIC_BUFFER_REF_HPP
#include <boost/beast/core/detail/config.hpp>
#include <boost/asio/buffer.hpp>
#include <cstdlib>
#include <type_traits>
namespace boost {
namespace beast {
/** A lightweight reference to a dynamic buffer.
Objects of this type meet the requirements of <em>DynamicBuffer</em>.
This is the wrapper returned by the function @ref dynamic_buffer_ref.
@see dynamic_buffer_ref
*/
template<class DynamicBuffer>
class dynamic_buffer_ref_wrapper
#if ! BOOST_BEAST_DOXYGEN
{
static_assert(net::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met");
DynamicBuffer& b_;
public:
using const_buffers_type = typename
DynamicBuffer::const_buffers_type;
using mutable_buffers_type = typename
DynamicBuffer::mutable_buffers_type;
dynamic_buffer_ref_wrapper(
dynamic_buffer_ref_wrapper&&) = default;
explicit
dynamic_buffer_ref_wrapper(
DynamicBuffer& b) noexcept
: b_(b)
{
}
std::size_t
size() const noexcept
{
return b_.size();
}
std::size_t
max_size() const noexcept
{
return b_.max_size();
}
std::size_t
capacity() const noexcept
{
return b_.capacity();
}
const_buffers_type
data() const noexcept
{
return b_.data();
}
mutable_buffers_type
prepare(std::size_t n)
{
return b_.prepare(n);
}
void
commit(std::size_t n)
{
b_.commit(n);
}
void
consume(std::size_t n)
{
b_.consume(n);
}
}
#endif
;
/** Return a non-owning reference to a dynamic buffer.
This function returns a wrapper which holds a reference to the
passed dynamic buffer. The wrapper meets the requirements of
<em>DynamicBuffer</em>, allowing its use in Networking algorithms
which want to take ownership of the dynamic buffer. Since Beast
dynamic buffers are true storage types, they cannot be used directly
with functions that take ownership of the dynamic buffer.
@par Example
This function reads a line of text from a stream into a
@ref flat_buffer, using the net function `async_read_until`. The
@code
template <class SyncReadStream>
std::size_t read_line (SyncReadStream& stream, flat_buffer& buffer)
{
return net::read_until(stream, dynamic_buffer_ref(buffer), "\r\n");
}
@endcode
@param buffer The dynamic buffer to wrap. Ownership of the buffer is
not transferred, the caller is still responsible for managing the
lifetime of the original object.
@return A wrapper meeting the requirements of <em>DynamicBuffer</em>
which references the original dynamic buffer.
@see dynamic_buffer_ref_wrapper
*/
template<class DynamicBuffer>
dynamic_buffer_ref_wrapper<DynamicBuffer>
dynamic_buffer_ref(DynamicBuffer& buffer) noexcept
{
static_assert(net::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met");
return dynamic_buffer_ref_wrapper<DynamicBuffer>(buffer);
}
} // beast
} // boost
#endif

View File

@@ -41,6 +41,7 @@ add_executable (tests-beast-core
buffers_suffix.cpp
buffers_to_string.cpp
close_socket.cpp
dynamic_buffer_ref.cpp
error.cpp
file.cpp
file_posix.cpp

View File

@@ -29,6 +29,7 @@ local SOURCES =
buffers_suffix.cpp
buffers_to_string.cpp
close_socket.cpp
dynamic_buffer_ref.cpp
error.cpp
file.cpp
file_posix.cpp

View File

@@ -0,0 +1,51 @@
//
// Copyright (c) 2018 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/dynamic_buffer_ref.hpp>
#include <boost/beast/_experimental/unit_test/suite.hpp>
#include <boost/beast/_experimental/test/stream.hpp>
#include <boost/beast/core/flat_buffer.hpp>
#include <boost/asio/read_until.hpp>
namespace boost {
namespace beast {
namespace {
template <class SyncReadStream>
std::size_t read_line (SyncReadStream& stream, flat_buffer& buffer)
{
return net::read_until(stream, dynamic_buffer_ref(buffer), "\r\n");
}
} // (anon)
class dynamic_buffer_ref_test : public beast::unit_test::suite
{
public:
void
testJavadocs()
{
BEAST_EXPECT(static_cast<
std::size_t(*)(test::stream&, flat_buffer&)>(
&read_line<test::stream>));
}
void run() override
{
testJavadocs();
}
};
BEAST_DEFINE_TESTSUITE(beast,core,dynamic_buffer_ref);
} // beast
} // boost