diff --git a/CHANGELOG.md b/CHANGELOG.md
index 09021deb..3819ddcf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@ Version 42
* Fix javadoc typo
* Add formal review notes
+* Make buffers_view a public interface
--------------------------------------------------------------------------------
diff --git a/doc/core.qbk b/doc/core.qbk
index 6b87f211..0088aaca 100644
--- a/doc/core.qbk
+++ b/doc/core.qbk
@@ -120,13 +120,12 @@ dynamic buffer concept using various strategies:
[table Dynamic buffer implementations
[[Name][Description]]
[[
- [link beast.ref.multi_buffer `multi_buffer`]
- [link beast.ref.basic_multi_buffer `basic_multi_buffer`]
+ [link beast.ref.buffers_adapter `buffers_adapter`]
][
- Uses a sequence of one or more character arrays of varying sizes.
- Additional character array objects are appended to the sequence to
- accommodate changes in the size of the character sequence. The basic
- container supports the standard allocator model.
+ This wrapper adapts any __MutableBufferSequence__ into a
+ __DynamicBuffer__ with an upper limit on the total size of the input and
+ output areas equal to the size of the underlying mutable buffer sequence.
+ The implementation does not perform heap allocations.
]]
[[
[link beast.ref.flat_buffer `flat_buffer`]
@@ -137,6 +136,15 @@ dynamic buffer concept using various strategies:
size of the input and output areas may be set. The basic container
supports the standard allocator model.
]]
+[[
+ [link beast.ref.multi_buffer `multi_buffer`]
+ [link beast.ref.basic_multi_buffer `basic_multi_buffer`]
+][
+ Uses a sequence of one or more character arrays of varying sizes.
+ Additional character array objects are appended to the sequence to
+ accommodate changes in the size of the character sequence. The basic
+ container supports the standard allocator model.
+]]
[[
[link beast.ref.static_buffer `static_buffer`]
[link beast.ref.static_buffer `static_buffer_n`]
@@ -146,14 +154,6 @@ dynamic buffer concept using various strategies:
by a constexpr template parameter. The storage for the sequences are
kept in the class; the implementation does not perform heap allocations.
]]
-[[
- [link beast.ref.buffers_adapter `buffers_adapter`]
-][
- This wrapper adapts any __MutableBufferSequence__ into a
- __DynamicBuffer__ with an upper limit on the total size of the input and
- output areas equal to the size of the underlying mutable buffer sequence.
- The implementation does not perform heap allocations.
-]]
]
[endsect]
@@ -180,6 +180,20 @@ underlying memory, whose lifetime is retained by the caller.
to a stream's `write_some` function to be combined into one, eliminating
expensive system calls.
]]
+[[
+ [link beast.ref.buffer_prefix `buffer_prefix`]
+][
+ This function returns a new buffer or buffer sequence which wraps the
+ underlying memory of an existing buffer sequence, but with a smaller size.
+ This lets callers work with a prefix of a buffer sequence.
+]]
+[[
+ [link beast.ref.buffer_cat `buffers_view`]
+][
+ This class represents a buffer sequence which represents the concatenation
+ of two or more buffer sequences. This is type of object returned by
+ [link beast.ref.buffer_cat `buffer_cat`].
+]]
[[
[link beast.ref.consuming_buffers `consuming_buffers`]
][
@@ -188,13 +202,6 @@ underlying memory, whose lifetime is retained by the caller.
may be progressively shortened. This lets callers work with sequential
increments of a buffer sequence.
]]
-[[
- [link beast.ref.buffer_prefix `buffer_prefix`]
-][
- This function returns a new buffer or buffer sequence which wraps the
- underlying memory of an existing buffer sequence, but with a smaller size.
- This lets callers work with a prefix of a buffer sequence.
-]]
]
[endsect]
@@ -236,12 +243,13 @@ the associated asynchronous initiation functions used to launch them.
[table Asynchronous Helpers
[[Name][Description]]
[[
- [link beast.ref.handler_type `handler_type`]
+ [link beast.ref.async_completion `async_completion`]
][
- This template alias converts a completion token and signature to the
- correct completion handler type. It is used in the implementation of
- asynchronous initiation functions to meet the requirements of the
- Extensible Asynchronous Model.
+ This class aggregates the completion handler customization point and
+ the asynchronous initiation function return value customization point
+ into a single object which exposes the appropriate output types for the
+ given input types, and also contains boilerplate that is necessary to
+ implement an initiation function using the Extensible Model.
]]
[[
[link beast.ref.async_return_type `async_return_type`]
@@ -252,13 +260,15 @@ the associated asynchronous initiation functions used to launch them.
Extensible Asynchronous Model.
]]
[[
- [link beast.ref.async_completion `async_completion`]
+ [link beast.ref.bind_handler `bind_handler`]
][
- This class aggregates the completion handler customization point and
- the asynchronous initiation function return value customization point
- into a single object which exposes the appropriate output types for the
- given input types, and also contains boilerplate that is necessary to
- implement an initiation function using the Extensible Model.
+ This function returns a new, nullary completion handler which when
+ invoked with no arguments invokes the original completion handler with a
+ list of bound arguments. The invocation is made from the same implicit
+ or explicit strand as that which would be used to invoke the original
+ handler. This is accomplished by using the correct overload of
+ `asio_handler_invoke` associated with the original completion handler.
+
]]
[[
[link beast.ref.handler_alloc `handler_alloc`]
@@ -282,15 +292,12 @@ the associated asynchronous initiation functions used to launch them.
optimizations transparently.
]]
[[
- [link beast.ref.bind_handler `bind_handler`]
+ [link beast.ref.handler_type `handler_type`]
][
- This function returns a new, nullary completion handler which when
- invoked with no arguments invokes the original completion handler with a
- list of bound arguments. The invocation is made from the same implicit
- or explicit strand as that which would be used to invoke the original
- handler. This is accomplished by using the correct overload of
- `asio_handler_invoke` associated with the original completion handler.
-
+ This template alias converts a completion token and signature to the
+ correct completion handler type. It is used in the implementation of
+ asynchronous initiation functions to meet the requirements of the
+ Extensible Asynchronous Model.
]]
]
diff --git a/doc/quickref.xml b/doc/quickref.xml
index d99617dd..42765b4e 100644
--- a/doc/quickref.xml
+++ b/doc/quickref.xml
@@ -157,6 +157,7 @@
basic_flat_bufferbasic_multi_bufferbuffers_adapter
+ buffers_viewconsuming_buffersbuffered_read_streamerror_category
diff --git a/include/beast/core/buffer_cat.hpp b/include/beast/core/buffer_cat.hpp
index 0f83393f..300d8c26 100644
--- a/include/beast/core/buffer_cat.hpp
+++ b/include/beast/core/buffer_cat.hpp
@@ -9,17 +9,67 @@
#define BEAST_BUFFER_CAT_HPP
#include
-#include
-#include
-#include
-#include
-#include
-#include
+#include
#include
-#include
namespace beast {
+/** A buffer sequence representing a concatenation of buffer sequences.
+
+ @see @ref buffer_cat
+*/
+template
+class buffers_view
+{
+ std::tuple bn_;
+
+public:
+ /** The type of buffer returned when dereferencing an iterator.
+
+ If every buffer sequence in the view is a @b MutableBufferSequence,
+ then `value_type` will be `boost::asio::mutable_buffer`.
+ Otherwise, `value_type` will be `boost::asio::const_buffer`.
+ */
+ using value_type =
+ #if BEAST_DOXYGEN
+ implementation_defined;
+ #else
+ typename detail::common_buffers_type::type;
+ #endif
+
+ /// The type of iterator used by the concatenated sequence
+ class const_iterator;
+
+ /// Move constructor
+ buffers_view(buffers_view&&) = default;
+
+ /// Copy constructor
+ buffers_view(buffers_view const&) = default;
+
+ /// Move assignment
+ buffers_view& operator=(buffers_view&&) = default;
+
+ // Copy assignment
+ buffers_view& operator=(buffers_view const&) = default;
+
+ /** Constructor
+
+ @param buffers The list of buffer sequences to concatenate.
+ Copies of the arguments will be made; however, the ownership
+ of memory is not transferred.
+ */
+ explicit
+ buffers_view(Buffers const&... buffers);
+
+ /// Return an iterator to the beginning of the concatenated sequence.
+ const_iterator
+ begin() const;
+
+ /// Return an iterator to the end of the concatenated sequence.
+ const_iterator
+ end() const;
+};
+
/** Concatenate 2 or more buffer sequences.
This function returns a constant or mutable buffer sequence which,
@@ -36,24 +86,28 @@ namespace beast {
@b MutableBufferSequence if each of the passed buffer sequences is
also a @b MutableBufferSequence; otherwise the returned buffer
sequence will be a @b ConstBufferSequence.
+
+ @see @ref buffers_view
*/
#if BEAST_DOXYGEN
template
-implementation_defined
+buffers_view
buffer_cat(BufferSequence const&... buffers)
#else
template
-detail::buffer_cat_helper
+inline
+buffers_view
buffer_cat(B1 const& b1, B2 const& b2, Bn const&... bn)
#endif
{
static_assert(
- detail::is_all_ConstBufferSequence::value,
+ detail::is_all_const_buffer_sequence::value,
"BufferSequence requirements not met");
- return detail::buffer_cat_helper<
- B1, B2, Bn...>{b1, b2, bn...};
+ return buffers_view{b1, b2, bn...};
}
} // beast
+#include
+
#endif
diff --git a/include/beast/core/detail/type_traits.hpp b/include/beast/core/detail/type_traits.hpp
index d3f24919..d3467b7d 100644
--- a/include/beast/core/detail/type_traits.hpp
+++ b/include/beast/core/detail/type_traits.hpp
@@ -244,20 +244,6 @@ public:
type3::value && type4::value>;
};
-template
-struct is_all_ConstBufferSequence
- : std::integral_constant::type::value &&
- is_all_ConstBufferSequence::value>
-{
-};
-
-template
-struct is_all_ConstBufferSequence
- : is_buffer_sequence::type
-{
-};
-
template
class is_dynamic_buffer
{
@@ -335,6 +321,33 @@ public:
//------------------------------------------------------------------------------
+template
+struct is_all_const_buffer_sequence
+ : std::integral_constant::type::value &&
+ is_all_const_buffer_sequence::value>
+{
+};
+
+template
+struct is_all_const_buffer_sequence
+ : is_buffer_sequence::type
+{
+};
+
+template
+struct common_buffers_type
+{
+ using type = typename std::conditional<
+ std::is_convertible,
+ typename repeat_tuple::type>::value,
+ boost::asio::mutable_buffer,
+ boost::asio::const_buffer>::type;
+};
+
+//------------------------------------------------------------------------------
+
//
// stream concepts
//
diff --git a/include/beast/core/detail/buffer_cat.hpp b/include/beast/core/impl/buffer_cat.ipp
similarity index 79%
rename from include/beast/core/detail/buffer_cat.hpp
rename to include/beast/core/impl/buffer_cat.ipp
index d441f0e4..38c8d1c6 100644
--- a/include/beast/core/detail/buffer_cat.hpp
+++ b/include/beast/core/impl/buffer_cat.ipp
@@ -5,10 +5,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-#ifndef BEAST_DETAIL_BUFFER_CAT_HPP
-#define BEAST_DETAIL_BUFFER_CAT_HPP
+#ifndef BEAST_IMPL_BUFFER_CAT_IPP
+#define BEAST_IMPL_BUFFER_CAT_IPP
-#include
+#include
#include
#include
#include
@@ -18,57 +18,16 @@
#include
namespace beast {
-namespace detail {
template
-struct common_buffers_type
-{
- using type = typename std::conditional<
- std::is_convertible,
- typename repeat_tuple::type>::value,
- boost::asio::mutable_buffer,
- boost::asio::const_buffer>::type;
-};
-
-template
-class buffer_cat_helper
-{
- std::tuple bn_;
-
-public:
- using value_type = typename
- common_buffers_type::type;
-
- class const_iterator;
-
- buffer_cat_helper(buffer_cat_helper&&) = default;
- buffer_cat_helper(buffer_cat_helper const&) = default;
- buffer_cat_helper& operator=(buffer_cat_helper&&) = delete;
- buffer_cat_helper& operator=(buffer_cat_helper const&) = delete;
-
- explicit
- buffer_cat_helper(Bn const&... bn)
- : bn_(bn...)
- {
- }
-
- const_iterator
- begin() const;
-
- const_iterator
- end() const;
-};
-
-template
-class buffer_cat_helper::const_iterator
+class buffers_view::const_iterator
{
std::size_t n_;
std::tuple const* bn_;
- std::array()> buf_;
+ char buf_[detail::max_sizeof<
+ typename Bn::const_iterator...>()];
- friend class buffer_cat_helper;
+ friend class buffers_view;
template
using C = std::integral_constant;
@@ -83,8 +42,7 @@ class buffer_cat_helper::const_iterator
{
// type-pun
return *reinterpret_cast<
- iter_t*>(static_cast(
- buf_.data()));
+ iter_t*>(static_cast(buf_));
}
template
@@ -94,12 +52,12 @@ class buffer_cat_helper::const_iterator
// type-pun
return *reinterpret_cast<
iter_t const*>(static_cast<
- void const*>(buf_.data()));
+ void const*>(buf_));
}
public:
using value_type = typename
- common_buffers_type::type;
+ detail::common_buffers_type::type;
using pointer = value_type const*;
using reference = value_type;
using difference_type = std::ptrdiff_t;
@@ -119,7 +77,7 @@ public:
bool
operator!=(const_iterator const& other) const
{
- return !(*this == other);
+ return ! (*this == other);
}
reference
@@ -169,7 +127,7 @@ private:
std::get(*bn_).end())
{
n_ = I;
- new(buf_.data()) iter_t{
+ new(buf_) iter_t{
std::get(*bn_).begin()};
return;
}
@@ -208,7 +166,7 @@ private:
{
if(n_ == I)
{
- new(buf_.data()) iter_t{
+ new(buf_) iter_t{
std::move(other.iter())};
return;
}
@@ -228,7 +186,7 @@ private:
{
if(n_ == I)
{
- new(buf_.data()) iter_t{
+ new(buf_) iter_t{
other.iter()};
return;
}
@@ -300,7 +258,7 @@ private:
if(n_ == I)
{
--n_;
- new(buf_.data()) iter_t{
+ new(buf_) iter_t{
std::get(*bn_).end()};
}
decrement(C{});
@@ -333,7 +291,7 @@ private:
--n_;
using Iter = iter_t;
iter().~Iter();
- new(buf_.data()) iter_t{
+ new(buf_) iter_t{
std::get(*bn_).end()};
}
decrement(C{});
@@ -343,14 +301,14 @@ private:
//------------------------------------------------------------------------------
template
-buffer_cat_helper::
+buffers_view::
const_iterator::~const_iterator()
{
destroy(C<0>{});
}
template
-buffer_cat_helper::
+buffers_view::
const_iterator::const_iterator()
: n_(sizeof...(Bn))
, bn_(nullptr)
@@ -358,7 +316,7 @@ const_iterator::const_iterator()
}
template
-buffer_cat_helper::
+buffers_view::
const_iterator::const_iterator(
std::tuple const& bn, bool at_end)
: bn_(&bn)
@@ -370,7 +328,7 @@ const_iterator::const_iterator(
}
template
-buffer_cat_helper::
+buffers_view::
const_iterator::const_iterator(const_iterator&& other)
: n_(other.n_)
, bn_(other.bn_)
@@ -379,7 +337,7 @@ const_iterator::const_iterator(const_iterator&& other)
}
template
-buffer_cat_helper::
+buffers_view::
const_iterator::const_iterator(const_iterator const& other)
: n_(other.n_)
, bn_(other.bn_)
@@ -389,7 +347,7 @@ const_iterator::const_iterator(const_iterator const& other)
template
auto
-buffer_cat_helper::
+buffers_view::
const_iterator::operator=(const_iterator&& other) ->
const_iterator&
{
@@ -404,7 +362,7 @@ const_iterator::operator=(const_iterator&& other) ->
template
auto
-buffer_cat_helper::
+buffers_view::
const_iterator::operator=(const_iterator const& other) ->
const_iterator&
{
@@ -419,7 +377,7 @@ const_iterator&
template
bool
-buffer_cat_helper::
+buffers_view::
const_iterator::operator==(const_iterator const& other) const
{
if(bn_ != other.bn_)
@@ -431,7 +389,7 @@ const_iterator::operator==(const_iterator const& other) const
template
auto
-buffer_cat_helper::
+buffers_view::
const_iterator::operator*() const ->
reference
{
@@ -440,7 +398,7 @@ const_iterator::operator*() const ->
template
auto
-buffer_cat_helper::
+buffers_view::
const_iterator::operator++() ->
const_iterator&
{
@@ -450,7 +408,7 @@ const_iterator::operator++() ->
template
auto
-buffer_cat_helper::
+buffers_view::
const_iterator::operator--() ->
const_iterator&
{
@@ -458,10 +416,20 @@ const_iterator::operator--() ->
return *this;
}
+//------------------------------------------------------------------------------
+
+template
+buffers_view::
+buffers_view(Bn const&... bn)
+ : bn_(bn...)
+{
+}
+
+
template
inline
auto
-buffer_cat_helper::begin() const ->
+buffers_view::begin() const ->
const_iterator
{
return const_iterator{bn_, false};
@@ -470,13 +438,12 @@ buffer_cat_helper::begin() const ->
template
inline
auto
-buffer_cat_helper::end() const ->
+buffers_view::end() const ->
const_iterator
{
return const_iterator{bn_, true};
}
-} // detail
} // beast
#endif
diff --git a/include/beast/http/chunk_encode.hpp b/include/beast/http/chunk_encode.hpp
index 082d2df1..ab7e883b 100644
--- a/include/beast/http/chunk_encode.hpp
+++ b/include/beast/http/chunk_encode.hpp
@@ -39,7 +39,7 @@ template
#if BEAST_DOXYGEN
implementation_defined
#else
-beast::detail::buffer_cat_helper<
+beast::buffers_view<
detail::chunk_encode_delim,
ConstBufferSequence,
boost::asio::const_buffers_1>
diff --git a/test/core/buffer_cat.cpp b/test/core/buffer_cat.cpp
index 688b315c..b9f2d932 100644
--- a/test/core/buffer_cat.cpp
+++ b/test/core/buffer_cat.cpp
@@ -215,29 +215,29 @@ public:
{
};
- // Check is_all_ConstBufferSequence
+ // Check is_all_const_buffer_sequence
static_assert(
- detail::is_all_ConstBufferSequence<
+ detail::is_all_const_buffer_sequence<
const_buffers_1
>::value, "");
static_assert(
- detail::is_all_ConstBufferSequence<
+ detail::is_all_const_buffer_sequence<
const_buffers_1, const_buffers_1
>::value, "");
static_assert(
- detail::is_all_ConstBufferSequence<
+ detail::is_all_const_buffer_sequence<
mutable_buffers_1
>::value, "");
static_assert(
- detail::is_all_ConstBufferSequence<
+ detail::is_all_const_buffer_sequence<
mutable_buffers_1, mutable_buffers_1
>::value, "");
static_assert(
- detail::is_all_ConstBufferSequence<
+ detail::is_all_const_buffer_sequence<
const_buffers_1, mutable_buffers_1
>::value, "");
static_assert(
- ! detail::is_all_ConstBufferSequence<
+ ! detail::is_all_const_buffer_sequence<
const_buffers_1, mutable_buffers_1, int
>::value, "");