Add buffers_range_ref (replaces reference_wrapper parameter)

This commit is contained in:
Vinnie Falco
2018-12-19 19:15:04 -08:00
parent cbd5e76e92
commit c4f4087888
14 changed files with 139 additions and 44 deletions

View File

@@ -22,6 +22,7 @@ Version 200
* HTTP tidying * HTTP tidying
* Adjust static_asio lib options in Jamfile * Adjust static_asio lib options in Jamfile
* Add type_traits tests * Add type_traits tests
* Add buffers_range_ref (replaces reference_wrapper parameter)
API Changes: API Changes:

View File

@@ -57,6 +57,7 @@ transferred.
]] ]]
[[ [[
[link beast.ref.boost__beast__buffers_range `buffers_range`] [link beast.ref.boost__beast__buffers_range `buffers_range`]
[link beast.ref.boost__beast__buffers_range_ref `buffers_range_ref`]
][ ][
This function returns an iterable range representing the passed This function returns an iterable range representing the passed
buffer sequence. The values obtained when iterating the range buffer sequence. The values obtained when iterating the range
@@ -64,6 +65,14 @@ transferred.
sequence is mutable, in which case the value obtained when iterating sequence is mutable, in which case the value obtained when iterating
will be a mutable buffer. It is intended as a notational convenience will be a mutable buffer. It is intended as a notational convenience
when writing a ['range-for] statement over a buffer sequence. when writing a ['range-for] statement over a buffer sequence.
The function
[link beast.ref.boost__beast__buffers_range_ref `buffers_range`]
maintains a copy of the buffer sequence, while
[link beast.ref.boost__beast__buffers_range_ref `buffers_range_ref`]
maintains a reference (in this case, the caller must ensure that
the lifetime of the referenced buffer sequence extends until the
range object is destroyed).
]] ]]
[[ [[
[link beast.ref.boost__beast__buffers_suffix `buffers_suffix`] [link beast.ref.boost__beast__buffers_suffix `buffers_suffix`]

View File

@@ -219,6 +219,7 @@
<member><link linkend="beast.ref.boost__beast__buffers_front">buffers_front</link></member> <member><link linkend="beast.ref.boost__beast__buffers_front">buffers_front</link></member>
<member><link linkend="beast.ref.boost__beast__buffers_prefix">buffers_prefix</link></member> <member><link linkend="beast.ref.boost__beast__buffers_prefix">buffers_prefix</link></member>
<member><link linkend="beast.ref.boost__beast__buffers_range">buffers_range</link></member> <member><link linkend="beast.ref.boost__beast__buffers_range">buffers_range</link></member>
<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__buffers_to_string">buffers_to_string</link></member>
<member><link linkend="beast.ref.boost__beast__generic_category">generic_category</link></member> <member><link linkend="beast.ref.boost__beast__generic_category">generic_category</link></member>
<member><link linkend="beast.ref.boost__beast__iequals">iequals</link></member> <member><link linkend="beast.ref.boost__beast__iequals">iequals</link></member>

View File

@@ -11,9 +11,8 @@
#define BOOST_BEAST_BUFFERS_RANGE_HPP #define BOOST_BEAST_BUFFERS_RANGE_HPP
#include <boost/beast/core/detail/config.hpp> #include <boost/beast/core/detail/config.hpp>
#include <boost/beast/core/buffer_traits.hpp>
#include <boost/beast/core/detail/buffers_range_adaptor.hpp> #include <boost/beast/core/detail/buffers_range_adaptor.hpp>
#include <boost/asio/buffer.hpp>
#include <functional>
namespace boost { namespace boost {
namespace beast { namespace beast {
@@ -22,65 +21,104 @@ namespace beast {
This function returns an iterable range representing the This function returns an iterable range representing the
passed buffer sequence. The values obtained when iterating passed buffer sequence. The values obtained when iterating
the range will always be `const_buffer`, unless the underlying the range will be `net::const_buffer`, unless the underlying
buffer sequence is a @em MutableBufferSequence, in which case buffer sequence is a <em>MutableBufferSequence</em>, in which case
the value obtained when iterating will be a `mutable_buffer`. the value obtained when iterating will be a `net::mutable_buffer`.
@par Example @par Example
The following function returns the total number of bytes in The following function returns the total number of bytes in
the specified buffer sequence: the specified buffer sequence. A copy of the buffer sequence
is maintained for the lifetime of the range object:
@code @code
template<class ConstBufferSequence> template <class BufferSequence>
std::size_t buffer_sequence_size(ConstBufferSequence const& buffers) std::size_t buffer_sequence_size (BufferSequence const& buffers)
{ {
std::size_t size = 0; std::size_t size = 0;
for(auto const buffer : buffers_range(std::ref(buffers))) for (auto const buffer : buffers_range (buffers))
size += buffer.size(); size += buffer.size();
return size; return size;
} }
@endcode @endcode
@param buffers The buffer sequence to adapt into a range. The @param buffers The buffer sequence to adapt into a range. The
range returned from this function will contain a copy of the range object returned from this function will contain a copy
passed buffer sequence. If `buffers` is a `std::reference_wrapper`, of the passed buffer sequence.
the range returned from this function will contain a reference to the
passed buffer sequence. In this case, the caller is responsible
for ensuring that the lifetime of the buffer sequence is valid for
the lifetime of the returned range.
@return An object of unspecified type, meeting the requirements of @return An object of unspecified type which meets the requirements
<em>ConstBufferSequence</em>, and also @em MutableBufferSequence if `buffers` of <em>ConstBufferSequence</em>. If `buffers` is a mutable buffer
is a mutable buffer sequence. sequence, the returned object will also meet the requirements of
<em>MutableBufferSequence</em>.
@see @ref buffers_range_ref
*/ */
/** @{ */ template<class BufferSequence>
template<class ConstBufferSequence>
#if BOOST_BEAST_DOXYGEN #if BOOST_BEAST_DOXYGEN
__implementation_defined__ __implementation_defined__
#else #else
detail::buffers_range_adaptor<ConstBufferSequence> detail::buffers_range_adaptor<BufferSequence>
#endif #endif
buffers_range(ConstBufferSequence const& buffers) buffers_range(BufferSequence const& buffers)
{ {
static_assert( static_assert(
net::is_const_buffer_sequence<ConstBufferSequence>::value, is_const_buffer_sequence<BufferSequence>::value,
"ConstBufferSequence requirements not met"); "BufferSequence requirements not met");
return detail::buffers_range_adaptor<ConstBufferSequence>(buffers); return detail::buffers_range_adaptor<
BufferSequence>(buffers);
} }
template<class ConstBufferSequence> /** Returns an iterable range representing a buffer sequence.
This function returns an iterable range representing the
passed buffer sequence. The values obtained when iterating
the range will be `net::const_buffer`, unless the underlying
buffer sequence is a <em>MutableBufferSequence</em>, in which case
the value obtained when iterating will be a `net::mutable_buffer`.
@par Example
The following function returns the total number of bytes in
the specified buffer sequence. A reference to the original
buffers is maintained for the lifetime of the range object:
@code
template <class BufferSequence>
std::size_t buffer_sequence_size_ref (BufferSequence const& buffers)
{
std::size_t size = 0;
for (auto const buffer : buffers_range_ref (buffers))
size += buffer.size();
return size;
}
@endcode
@param buffers The buffer sequence to adapt into a range. The
range returned from this function will maintain a reference to
these buffers. The application is responsible for ensuring that
the lifetime of the referenced buffers extends until the range
object is destroyed.
@return An object of unspecified type which meets the requirements
of <em>ConstBufferSequence</em>. If `buffers` is a mutable buffer
sequence, the returned object will also meet the requirements of
<em>MutableBufferSequence</em>.
@see @ref buffers_range
*/
template<class BufferSequence>
#if BOOST_BEAST_DOXYGEN #if BOOST_BEAST_DOXYGEN
__implementation_defined__ __implementation_defined__
#else #else
detail::buffers_range_adaptor<ConstBufferSequence const&> detail::buffers_range_adaptor<BufferSequence const&>
#endif #endif
buffers_range(std::reference_wrapper<ConstBufferSequence> buffers) buffers_range_ref(BufferSequence const& buffers)
{ {
static_assert( static_assert(
net::is_const_buffer_sequence<ConstBufferSequence>::value, is_const_buffer_sequence<BufferSequence>::value,
"ConstBufferSequence requirements not met"); "BufferSequence requirements not met");
return detail::buffers_range_adaptor<ConstBufferSequence const&>(buffers.get()); return detail::buffers_range_adaptor<
BufferSequence const&>(buffers);
} }
/** @} */ /** @} */

View File

@@ -50,7 +50,7 @@ buffers_to_string(ConstBufferSequence const& buffers)
std::string result; std::string result;
using net::buffer_size; using net::buffer_size;
result.reserve(buffer_size(buffers)); result.reserve(buffer_size(buffers));
for(auto const buffer : beast::buffers_range(std::ref(buffers))) for(auto const buffer : beast::buffers_range_ref(buffers))
result.append(static_cast<char const*>( result.append(static_cast<char const*>(
buffer.data()), buffer.size()); buffer.data()), buffer.size());
return result; return result;

View File

@@ -192,7 +192,7 @@ struct basic_file_body<file_win32>
error_code& ec) error_code& ec)
{ {
std::size_t nwritten = 0; std::size_t nwritten = 0;
for(auto buffer : beast::buffers_range(std::ref(buffers))) for(auto buffer : beast::buffers_range_ref(buffers))
{ {
nwritten += body_.file_.write( nwritten += body_.file_.write(
buffer.data(), buffer.size(), ec); buffer.data(), buffer.size(), ec);

View File

@@ -936,7 +936,7 @@ public:
if(os_.fail()) if(os_.fail())
return; return;
std::size_t bytes_transferred = 0; std::size_t bytes_transferred = 0;
for(auto b : beast::buffers_range(std::ref(buffers))) for(auto b : beast::buffers_range_ref(buffers))
{ {
os_.write(static_cast<char const*>( os_.write(static_cast<char const*>(
b.data()), b.size()); b.data()), b.size());

View File

@@ -132,7 +132,7 @@ public:
} }
ec.assign(0, ec.category()); ec.assign(0, ec.category());
CharT* dest = &body_[size]; CharT* dest = &body_[size];
for(auto b : beast::buffers_range(std::ref(buffers))) for(auto b : beast::buffers_range_ref(buffers))
{ {
Traits::copy(dest, static_cast< Traits::copy(dest, static_cast<
CharT const*>(b.data()), b.size()); CharT const*>(b.data()), b.size());

View File

@@ -71,12 +71,16 @@ mask_inplace(net::mutable_buffer& b, prepared_key& key)
// Apply mask in place // Apply mask in place
// //
template<class MutableBuffers, class KeyType> template<
class MutableBufferSequence,
class KeyType>
void void
mask_inplace(MutableBuffers const& bs, KeyType& key) mask_inplace(
MutableBufferSequence const& buffers,
KeyType& key)
{ {
for(net::mutable_buffer b : for(net::mutable_buffer b :
beast::buffers_range(std::ref(bs))) beast::buffers_range_ref(buffers))
mask_inplace(b, key); mask_inplace(b, key);
} }

View File

@@ -84,11 +84,12 @@ template<class _>
template<class ConstBufferSequence> template<class ConstBufferSequence>
bool bool
utf8_checker_t<_>:: utf8_checker_t<_>::
write(ConstBufferSequence const& bs) write(ConstBufferSequence const& buffers)
{ {
static_assert(net::is_const_buffer_sequence<ConstBufferSequence>::value, static_assert(
net::is_const_buffer_sequence<ConstBufferSequence>::value,
"ConstBufferSequence requirements not met"); "ConstBufferSequence requirements not met");
for(auto b : beast::buffers_range(std::ref(bs))) for(auto b : beast::buffers_range_ref(buffers))
if(! write(static_cast< if(! write(static_cast<
std::uint8_t const*>(b.data()), std::uint8_t const*>(b.data()),
b.size())) b.size()))

View File

@@ -60,7 +60,7 @@ deflate(
zs.next_in = nullptr; zs.next_in = nullptr;
zs.avail_out = out.size(); zs.avail_out = out.size();
zs.next_out = out.data(); zs.next_out = out.data();
for(auto in : beast::buffers_range(std::ref(cb))) for(auto in : beast::buffers_range_ref(cb))
{ {
zs.avail_in = in.size(); zs.avail_in = in.size();
if(zs.avail_in == 0) if(zs.avail_in == 0)

View File

@@ -20,11 +20,51 @@ namespace beast {
class buffers_range_test : public beast::unit_test::suite class buffers_range_test : public beast::unit_test::suite
{ {
public: public:
BOOST_STATIC_ASSERT(
is_const_buffer_sequence<
decltype(beast::buffers_range(
std::declval<net::const_buffer>()))>::value);
BOOST_STATIC_ASSERT(
is_const_buffer_sequence<
decltype(beast::buffers_range(
std::declval<net::mutable_buffer>()))>::value);
BOOST_STATIC_ASSERT(
! net::is_mutable_buffer_sequence<
decltype(beast::buffers_range(
std::declval<net::const_buffer>()))>::value);
BOOST_STATIC_ASSERT( BOOST_STATIC_ASSERT(
net::is_mutable_buffer_sequence< net::is_mutable_buffer_sequence<
decltype(beast::buffers_range( decltype(beast::buffers_range(
std::declval<net::mutable_buffer>()))>::value); std::declval<net::mutable_buffer>()))>::value);
template <class BufferSequence>
std::size_t buffer_sequence_size (BufferSequence const& buffers)
{
std::size_t size = 0;
for (auto const buffer : buffers_range (buffers))
size += buffer.size();
return size;
}
template <class BufferSequence>
std::size_t buffer_sequence_size_ref (BufferSequence const& buffers)
{
std::size_t size = 0;
for (auto const buffer : buffers_range_ref (buffers))
size += buffer.size();
return size;
}
void
testJavadocs()
{
BEAST_EXPECT(&buffers_range_test::buffer_sequence_size<net::const_buffer>);
BEAST_EXPECT(&buffers_range_test::buffer_sequence_size_ref<net::const_buffer>);
}
void void
testBufferSequence() testBufferSequence()
{ {
@@ -44,6 +84,7 @@ public:
void void
run() override run() override
{ {
testJavadocs();
testBufferSequence(); testBufferSequence();
} }
}; };

View File

@@ -68,7 +68,7 @@ public:
fill(MutableBufferSequence const& buffers) fill(MutableBufferSequence const& buffers)
{ {
std::size_t n = 0; std::size_t n = 0;
for(auto b : beast::buffers_range(std::ref(buffers))) for(auto b : beast::buffers_range_ref(buffers))
{ {
std::fill( std::fill(
static_cast<char*>(b.data()), static_cast<char*>(b.data()),

View File

@@ -269,7 +269,7 @@ nodejs_basic_parser<Derived>::write(
ConstBufferSequence>::value, ConstBufferSequence>::value,
"ConstBufferSequence requirements not met"); "ConstBufferSequence requirements not met");
std::size_t bytes_used = 0; std::size_t bytes_used = 0;
for(auto buffer : beast::buffers_range(std::ref(buffers))) for(auto buffer : beast::buffers_range_ref(buffers))
{ {
auto const n = write( auto const n = write(
static_cast<void const*>(buffer.data()), static_cast<void const*>(buffer.data()),