Add buffers_range

This commit is contained in:
Vinnie Falco
2018-11-11 20:59:57 -08:00
parent 450964b78f
commit 071cab92d5
21 changed files with 283 additions and 137 deletions

View File

@ -2,6 +2,7 @@ Version 190:
* Add missing includes to convenience headers
* Unit test framework is experimental
* Add buffers_range
--------------------------------------------------------------------------------

View File

@ -55,6 +55,16 @@ transferred.
an existing buffer sequence. This is the type of buffer returned by
[link beast.ref.boost__beast__buffers_prefix.overload3 `buffers_prefix`].
]]
[[
[link beast.ref.boost__beast__buffers_range `buffers_range`]
][
This function returns an iterable range representing the passed
buffer sequence. The values obtained when iterating the range
will always be a constant buffer, unless the underlying buffer
sequence is mutable, in which case the value obtained when iterating
will be a mutable buffer. It is intended as a notational convenience
when writing a ['range-for] statement over a buffer sequence.
]]
[[
[link beast.ref.boost__beast__buffers_suffix `buffers_suffix`]
][

View File

@ -217,6 +217,7 @@
<member><link linkend="beast.ref.boost__beast__buffers_cat">buffers_cat</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_range">buffers_range</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__iequals">iequals</link></member>

View File

@ -38,7 +38,7 @@ BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
DISTRIBUTE_GROUP_DOC = YES
GROUP_NESTED_COMPOUNDS = NO
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO

View File

@ -17,6 +17,7 @@
#include <boost/beast/core/buffers_adapter.hpp>
#include <boost/beast/core/buffers_cat.hpp>
#include <boost/beast/core/buffers_prefix.hpp>
#include <boost/beast/core/buffers_range.hpp>
#include <boost/beast/core/buffers_suffix.hpp>
#include <boost/beast/core/buffers_to_string.hpp>
#include <boost/beast/core/error.hpp>

View File

@ -0,0 +1,90 @@
//
// 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_RANGE_HPP
#define BOOST_BEAST_BUFFERS_RANGE_HPP
#include <boost/beast/core/detail/config.hpp>
#include <boost/beast/core/detail/buffers_range.hpp>
#include <boost/asio/buffer.hpp>
#include <functional>
namespace boost {
namespace beast {
/** Return a range representing a const or mutable buffer sequence.
This function returns an iterable range representing the
passed buffer sequence. The values obtained when iterating
the range will always be `const_buffer`, unless the underlying
buffer sequence is a @em MutableBufferSequence, in which case
the value obtained when iterating will be a `mutable_buffer`.
@par Example
The following function returns the total number of bytes in
the specified buffer sequence:
@code
template<class ConstBufferSequence>
std::size_t buffer_sequence_size(ConstBufferSequence const& buffers)
{
std::size_t size = 0;
for(auto const buffer : buffers_range(std::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 contain a copy of the
passed buffer sequence. If `buffers` is a `std::reference_wrapper`,
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
@em ConstBufferSequence, or @em MutableBufferSequence if `buffers`
is a mutable buffer sequence.
*/
/** @{ */
template<class ConstBufferSequence>
#if BOOST_BEAST_DOXYGEN
__implementation_defined__
#else
detail::buffers_range_adaptor<ConstBufferSequence>
#endif
buffers_range(ConstBufferSequence const& buffers)
{
static_assert(
boost::asio::is_const_buffer_sequence<ConstBufferSequence>::value,
"ConstBufferSequence requirements not met");
return detail::buffers_range_adaptor<ConstBufferSequence>(buffers);
}
template<class ConstBufferSequence>
#if BOOST_BEAST_DOXYGEN
__implementation_defined__
#else
detail::buffers_range_adaptor<ConstBufferSequence const&>
#endif
buffers_range(std::reference_wrapper<ConstBufferSequence> buffers)
{
static_assert(
boost::asio::is_const_buffer_sequence<ConstBufferSequence>::value,
"ConstBufferSequence requirements not met");
return detail::buffers_range_adaptor<ConstBufferSequence const&>(buffers.get());
}
/** @} */
} // beast
} // boost
#endif

View File

@ -11,7 +11,7 @@
#define BOOST_BEAST_BUFFERS_TO_STRING_HPP
#include <boost/beast/core/detail/config.hpp>
#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/beast/core/buffers_range.hpp>
#include <boost/asio/buffer.hpp>
#include <string>
@ -41,16 +41,17 @@ namespace beast {
@endcode
*/
template<class ConstBufferSequence>
inline
std::string
buffers_to_string(ConstBufferSequence const& buffers)
{
static_assert(
boost::asio::is_const_buffer_sequence<ConstBufferSequence>::value,
"ConstBufferSequence requirements not met");
std::string result;
result.reserve(boost::asio::buffer_size(buffers));
for(boost::asio::const_buffer buffer :
detail::buffers_range(buffers))
result.append(static_cast<
char const*>(buffer.data()), buffer.size());
for(auto const buffer : buffers_range(std::ref(buffers)))
result.append(static_cast<char const*>(
buffer.data()), buffer.size());
return result;
}

View File

@ -0,0 +1,141 @@
//
// 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_DETAIL_BUFFERS_RANGE_HPP
#define BOOST_BEAST_DETAIL_BUFFERS_RANGE_HPP
#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/asio/buffer.hpp>
#include <iterator>
#include <type_traits>
namespace boost {
namespace beast {
namespace detail {
template<class BufferSequence>
class buffers_range_adaptor
{
BufferSequence b_;
public:
#if BOOST_BEAST_DOXYGEN
using value_type = __see_below__;
#else
using value_type = typename std::conditional<
boost::is_convertible<
typename std::iterator_traits<
typename detail::buffer_sequence_iterator<
BufferSequence>::type>::value_type,
boost::asio::mutable_buffer>::value,
boost::asio::mutable_buffer,
boost::asio::const_buffer>::type;
#endif
class const_iterator
{
friend class buffers_range_adaptor;
using iter_type = typename
buffer_sequence_iterator<BufferSequence>::type;
iter_type it_;
const_iterator(iter_type const& it)
: it_(it)
{
}
public:
using value_type = typename
buffers_range_adaptor::value_type;
using pointer = value_type const*;
using reference = value_type;
using difference_type = std::ptrdiff_t;
using iterator_category =
std::bidirectional_iterator_tag;
bool
operator==(const_iterator const& other) const
{
return it_ == other.it_;
}
bool
operator!=(const_iterator const& other) const
{
return ! (*this == other);
}
reference
operator*() const
{
return *it_;
}
pointer
operator->() const = delete;
const_iterator&
operator++()
{
++it_;
return *this;
}
const_iterator
operator++(int)
{
auto temp = *this;
++(*this);
return temp;
}
// deprecated
const_iterator&
operator--()
{
--it_;
return *this;
}
// deprecated
const_iterator
operator--(int)
{
auto temp = *this;
--(*this);
return temp;
}
};
explicit
buffers_range_adaptor(BufferSequence const& b)
: b_(b)
{
}
const_iterator
begin() const noexcept
{
return boost::asio::buffer_sequence_begin(b_);
}
const_iterator
end() const noexcept
{
return boost::asio::buffer_sequence_end(b_);
}
};
} // detail
} // beast
} // boost
#endif

View File

@ -48,7 +48,7 @@ std::ostream&
operator<<(std::ostream& os,
buffers_helper<Buffers> const& v)
{
for(auto b : buffers_range(v.b_))
for(auto b : buffers_range(std::ref(v.b_)))
os.write(static_cast<char const*>(b.data()), b.size());
return os;
}

View File

@ -336,124 +336,6 @@ struct StreamHandler
using ReadHandler = StreamHandler;
using WriteHandler = StreamHandler;
template<class Buffers>
class buffers_range_adaptor
{
Buffers const& b_;
public:
using value_type = typename std::conditional<
boost::is_convertible<
typename std::iterator_traits<
typename buffer_sequence_iterator<
Buffers>::type>::value_type,
boost::asio::mutable_buffer>::value,
boost::asio::mutable_buffer,
boost::asio::const_buffer>::type;
class const_iterator
{
friend class buffers_range_adaptor;
using iter_type = typename
buffer_sequence_iterator<Buffers>::type;
iter_type it_;
const_iterator(iter_type const& it)
: it_(it)
{
}
public:
using value_type = typename
buffers_range_adaptor::value_type;
using pointer = value_type const*;
using reference = value_type;
using difference_type = std::ptrdiff_t;
using iterator_category =
std::bidirectional_iterator_tag;
bool
operator==(const_iterator const& other) const
{
return it_ == other.it_;
}
bool
operator!=(const_iterator const& other) const
{
return ! (*this == other);
}
reference
operator*() const
{
return *it_;
}
pointer
operator->() const = delete;
const_iterator&
operator++()
{
++it_;
return *this;
}
const_iterator
operator++(int)
{
auto temp = *this;
++(*this);
return temp;
}
// deprecated
const_iterator&
operator--()
{
--it_;
return *this;
}
// deprecated
const_iterator
operator--(int)
{
auto temp = *this;
--(*this);
return temp;
}
};
explicit
buffers_range_adaptor(Buffers const& b)
: b_(b)
{
}
const_iterator
begin() const noexcept
{
return boost::asio::buffer_sequence_begin(b_);
}
const_iterator
end() const noexcept
{
return boost::asio::buffer_sequence_end(b_);
}
};
template<class Buffers>
buffers_range_adaptor<Buffers>
buffers_range(Buffers const& buffers)
{
return buffers_range_adaptor<Buffers>{buffers};
}
/* If this static assert goes off, it means that the completion
handler you provided to an asynchronous initiating function did
not have the right signature. Check the parameter types for your

View File

@ -13,6 +13,7 @@
#if BOOST_BEAST_USE_WIN32_FILE
#include <boost/beast/core/bind_handler.hpp>
#include <boost/beast/core/buffers_range.hpp>
#include <boost/beast/core/type_traits.hpp>
#include <boost/beast/core/detail/clamp.hpp>
#include <boost/beast/http/serializer.hpp>
@ -191,7 +192,7 @@ struct basic_file_body<file_win32>
error_code& ec)
{
std::size_t nwritten = 0;
for(auto buffer : beast::detail::buffers_range(buffers))
for(auto buffer : beast::buffers_range(std::ref(buffers)))
{
nwritten += body_.file_.write(
buffer.data(), buffer.size(), ec);

View File

@ -12,8 +12,9 @@
#include <boost/beast/http/type_traits.hpp>
#include <boost/beast/core/bind_handler.hpp>
#include <boost/beast/core/ostream.hpp>
#include <boost/beast/core/buffers_range.hpp>
#include <boost/beast/core/handler_ptr.hpp>
#include <boost/beast/core/ostream.hpp>
#include <boost/beast/core/type_traits.hpp>
#include <boost/beast/core/detail/config.hpp>
#include <boost/asio/associated_allocator.hpp>
@ -935,7 +936,7 @@ public:
if(os_.fail())
return;
std::size_t bytes_transferred = 0;
for(auto b : buffers_range(buffers))
for(auto b : beast::buffers_range(std::ref(buffers)))
{
os_.write(static_cast<char const*>(
b.data()), b.size());

View File

@ -13,6 +13,7 @@
#include <boost/beast/core/detail/config.hpp>
#include <boost/beast/http/error.hpp>
#include <boost/beast/http/message.hpp>
#include <boost/beast/core/buffers_range.hpp>
#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/optional.hpp>
@ -131,7 +132,7 @@ public:
}
ec.assign(0, ec.category());
CharT* dest = &body_[size];
for(auto b : beast::detail::buffers_range(buffers))
for(auto b : beast::buffers_range(std::ref(buffers)))
{
Traits::copy(dest, static_cast<
CharT const*>(b.data()), b.size());

View File

@ -11,7 +11,7 @@
#define BOOST_BEAST_WEBSOCKET_DETAIL_MASK_HPP
#include <boost/beast/core/detail/config.hpp>
#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/beast/core/buffers_range.hpp>
#include <boost/asio/buffer.hpp>
#include <array>
#include <climits>
@ -76,7 +76,7 @@ void
mask_inplace(MutableBuffers const& bs, KeyType& key)
{
for(boost::asio::mutable_buffer b :
beast::detail::buffers_range(bs))
beast::buffers_range(std::ref(bs)))
mask_inplace(b, key);
}

View File

@ -10,7 +10,7 @@
#ifndef BOOST_BEAST_WEBSOCKET_DETAIL_UTF8_CHECKER_HPP
#define BOOST_BEAST_WEBSOCKET_DETAIL_UTF8_CHECKER_HPP
#include <boost/beast/core/type_traits.hpp>
#include <boost/beast/core/buffers_range.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/assert.hpp>
#include <algorithm>
@ -88,7 +88,7 @@ write(ConstBufferSequence const& bs)
{
static_assert(boost::asio::is_const_buffer_sequence<ConstBufferSequence>::value,
"ConstBufferSequence requirements not met");
for(auto b : beast::detail::buffers_range(bs))
for(auto b : beast::buffers_range(std::ref(bs)))
if(! write(static_cast<
std::uint8_t const*>(b.data()),
b.size()))

View File

@ -13,6 +13,7 @@
#include <boost/beast/core/bind_handler.hpp>
#include <boost/beast/core/buffers_cat.hpp>
#include <boost/beast/core/buffers_prefix.hpp>
#include <boost/beast/core/buffers_range.hpp>
#include <boost/beast/core/buffers_suffix.hpp>
#include <boost/beast/core/flat_static_buffer.hpp>
#include <boost/beast/core/type_traits.hpp>
@ -59,7 +60,7 @@ deflate(
zs.next_in = nullptr;
zs.avail_out = out.size();
zs.next_out = out.data();
for(auto in : beast::detail::buffers_range(cb))
for(auto in : beast::buffers_range(std::ref(cb)))
{
zs.avail_in = in.size();
if(zs.avail_in == 0)

View File

@ -24,6 +24,7 @@ add_executable (tests-beast-core
buffers_adapter.cpp
buffers_cat.cpp
buffers_prefix.cpp
buffers_range.cpp
buffers_suffix.cpp
buffers_to_string.cpp
error.cpp

View File

@ -14,6 +14,7 @@ local SOURCES =
buffers_adapter.cpp
buffers_cat.cpp
buffers_prefix.cpp
buffers_range.cpp
buffers_suffix.cpp
buffers_to_string.cpp
error.cpp

View File

@ -0,0 +1,11 @@
//
// 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_range.hpp>

View File

@ -7,6 +7,7 @@
// Official repository: https://github.com/boostorg/beast
//
#include <boost/beast/core/buffers_range.hpp>
#include <boost/beast/core/flat_buffer.hpp>
#include <boost/beast/core/multi_buffer.hpp>
#include <boost/beast/core/read_size.hpp>
@ -67,7 +68,7 @@ public:
fill(MutableBufferSequence const& buffers)
{
std::size_t n = 0;
for(auto b : beast::detail::buffers_range(buffers))
for(auto b : beast::buffers_range(std::ref(buffers)))
{
std::fill(
static_cast<char*>(b.data()),

View File

@ -14,6 +14,7 @@
#include <boost/beast/http/message.hpp>
#include <boost/beast/http/rfc7230.hpp>
#include <boost/beast/core/buffers_range.hpp>
#include <boost/beast/core/error.hpp>
#include <boost/beast/core/type_traits.hpp>
#include <boost/asio/buffer.hpp>
@ -268,7 +269,7 @@ nodejs_basic_parser<Derived>::write(
ConstBufferSequence>::value,
"ConstBufferSequence requirements not met");
std::size_t bytes_used = 0;
for(auto buffer : beast::detail::buffers_range(buffers))
for(auto buffer : beast::buffers_range(std::ref(buffers)))
{
auto const n = write(
static_cast<void const*>(buffer.data()),