Rename concept to DynamicBuffer (API change):

Conform to the Networking TS by renaming the Streambuf concept
to DynamicBuffer in all places. Values of types meeting the
requirements of DynamicBuffer are renamed to dynabuf.

See:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4478.html#requirements.dynamic_buffers

* Headers renamed
* Formal parameter names renamed
* Template argument types renamed
* Documentation updated
This commit is contained in:
Vinnie Falco
2016-05-28 09:23:54 -04:00
parent e8019fa9d4
commit 6c30ee1a98
41 changed files with 676 additions and 612 deletions

View File

@@ -11,4 +11,7 @@ API Changes:
* ci_equal is moved to beast::http namespace, in rfc7230.hpp * ci_equal is moved to beast::http namespace, in rfc7230.hpp
* "DynamicBuffer","dynabuf" renamed from "Streambuf", "streambuf". See:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4478.html#requirements.dynamic_buffers
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

View File

@@ -15,6 +15,11 @@ Requirements:
* C++11 or greater * C++11 or greater
* OpenSSL (optional) * OpenSSL (optional)
This software is currently in beta: interfaces are subject to change. For
recent changes see [CHANGELOG](CHANGELOG).
The library has been submitted to the
[Boost Library Incubator](http://rrsd.com/blincubator.com/bi_library/beast-2/?gform_post_id=1579)
Example WebSocket program: Example WebSocket program:
```C++ ```C++
#include <beast/to_string.hpp> #include <beast/to_string.hpp>

View File

@@ -192,11 +192,11 @@ supporting its development.
[section:types Type Requirements] [section:types Type Requirements]
[include types/Body.qbk] [include types/Body.qbk]
[include types/BufferSequence.qbk] [include types/BufferSequence.qbk]
[include types/DynamicBuffer.qbk]
[include types/Field.qbk] [include types/Field.qbk]
[include types/FieldSequence.qbk] [include types/FieldSequence.qbk]
[include types/Parser.qbk] [include types/Parser.qbk]
[include types/Reader.qbk] [include types/Reader.qbk]
[include types/Streambuf.qbk]
[include types/Streams.qbk] [include types/Streams.qbk]
[include types/Writer.qbk] [include types/Writer.qbk]
[endsect] [endsect]

View File

@@ -25,13 +25,13 @@ libraries:
* Let library users make the important decisions such as how to * Let library users make the important decisions such as how to
allocate memory or how to leverage flow control. allocate memory or how to leverage flow control.
Beast formalizes the [link beast.types.Streambuf [*`Streambuf`]] concept, Beast uses the [link beast.types.DynamicBuffer [*`DynamicBuffer`]] concept
and relies heavily on the Boost.Asio [*`ConstBufferSequence`] and presented in the Netwoking TS, and relies heavily on the Boost.Asio
[*`MutableBufferSequence`] concepts for passing buffers to functions. [*`ConstBufferSequence`] and [*`MutableBufferSequence`] concepts for passing
The authors have found the `Streambuf` and buffer sequence interfaces buffers to functions. The authors have found the dynamic buffer and buffer
to be optimal for interacting with Asio, and for other tasks such as sequence interfaces to be optimal for interacting with Asio, and for other
incremental parsing of data in buffers (for example, parsing websocket tasks such as incremental parsing of data in buffers (for example, parsing
frames stored in a [link beast.ref.static_streambuf `static_streambuf`]). websocket frames stored in a [link beast.ref.static_streambuf `static_streambuf`]).
During the development of Beast the authors have studied other software During the development of Beast the authors have studied other software
packages and in particular the comments left during the Boost Review process packages and in particular the comments left during the Boost Review process

View File

@@ -182,21 +182,9 @@ used in the examples:
resp.body = "Here is the data you requested"; resp.body = "Here is the data you requested";
``` ```
* [link beast.ref.http__basic_streambuf_body [*`basic_streambuf_body`:]] A body with a * [link beast.ref.http__streambuf_body [*`streambuf_body`:]] A body with a
`value_type` of `streambuf`. A streambuf is an efficient storage object which `value_type` of [link beast.ref.streambuf `streambuf`]: an efficient storage
uses multiple octet arrays of varying lengths to represent data. Here is object which uses multiple octet arrays of varying lengths to represent data.
a body that uses a `boost::asio::streambuf` as its container:
```
template<class ConstBufferSequence>
http::response<http::basic_streambuf_body<boost::asio::streambuf>>
make_response(ConstBufferSequence const& buffers)
{
http::response<http::streambuf_body<boost::asio::streambuf>> resp;
resp.body.commit(boost::asio::buffer_copy(resp.body.prepare(
boost::asio::buffer_size(buffers)), buffers));
return resp;
}
```
[heading Sockets] [heading Sockets]
@@ -234,7 +222,7 @@ When the implementation reads messages from a socket, it can read bytes lying
after the end of the message if they are present (the alternative is to read after the end of the message if they are present (the alternative is to read
a single byte at a time which is unsuitable for performance reasons). To a single byte at a time which is unsuitable for performance reasons). To
store and re-use these extra bytes on subsequent messages, the read interface store and re-use these extra bytes on subsequent messages, the read interface
requires an additional paramter: a [link beast.types.Streambuf [*`Streambuf`]] requires an additional paramter: a [link beast.types.DynamicBuffer [*`DynamicBuffer`]]
object. This example reads a message from the socket, with the extra bytes object. This example reads a message from the socket, with the extra bytes
stored in the streambuf parameter for use in a subsequent call to read: stored in the streambuf parameter for use in a subsequent call to read:
``` ```
@@ -264,7 +252,7 @@ called:
An alternative to using a `boost::asio::streambuf` is to use a An alternative to using a `boost::asio::streambuf` is to use a
[link beast.ref.streambuf `beast::streambuf`], which meets the requirements of [link beast.ref.streambuf `beast::streambuf`], which meets the requirements of
[*`Streambuf`] and is optimized for performance: [*`DynamicBuffer`] and is optimized for performance:
``` ```
void handle_read(boost::system::error_code); void handle_read(boost::system::error_code);
... ...
@@ -274,7 +262,7 @@ An alternative to using a `boost::asio::streambuf` is to use a
``` ```
The `read` implementation can use any object meeting the requirements of The `read` implementation can use any object meeting the requirements of
[link beast.types.Streambuf [*`Streambuf`]], allowing callers to define custom [link beast.types.DynamicBuffer [*`DynamicBuffer`]], allowing callers to define custom
memory management strategies used by the implementation. memory management strategies used by the implementation.
[endsect] [endsect]

View File

@@ -29,9 +29,9 @@
<entry valign="top"> <entry valign="top">
<bridgehead renderas="sect3">Classes</bridgehead> <bridgehead renderas="sect3">Classes</bridgehead>
<simplelist type="vert" columns="1"> <simplelist type="vert" columns="1">
<member><link linkend="beast.ref.http__basic_dynabuf_body">basic_dynabuf_body</link></member>
<member><link linkend="beast.ref.http__basic_headers">basic_headers</link></member> <member><link linkend="beast.ref.http__basic_headers">basic_headers</link></member>
<member><link linkend="beast.ref.http__basic_parser_v1">basic_parser_v1</link></member> <member><link linkend="beast.ref.http__basic_parser_v1">basic_parser_v1</link></member>
<member><link linkend="beast.ref.http__basic_streambuf_body">basic_streambuf_body</link></member>
<member><link linkend="beast.ref.http__empty_body">empty_body</link></member> <member><link linkend="beast.ref.http__empty_body">empty_body</link></member>
<member><link linkend="beast.ref.http__headers">headers</link></member> <member><link linkend="beast.ref.http__headers">headers</link></member>
<member><link linkend="beast.ref.http__message">message</link></member> <member><link linkend="beast.ref.http__message">message</link></member>
@@ -130,6 +130,7 @@
<member><link linkend="beast.ref.basic_streambuf">basic_streambuf</link></member> <member><link linkend="beast.ref.basic_streambuf">basic_streambuf</link></member>
<member><link linkend="beast.ref.buffers_adapter">buffers_adapter</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.consuming_buffers">consuming_buffers</link></member>
<member><link linkend="beast.ref.dynabuf_readstream">dynabuf_readstream</link></member>
<member><link linkend="beast.ref.error_code">error_code</link></member> <member><link linkend="beast.ref.error_code">error_code</link></member>
<member><link linkend="beast.ref.handler_alloc">handler_alloc</link></member> <member><link linkend="beast.ref.handler_alloc">handler_alloc</link></member>
<member><link linkend="beast.ref.prepared_buffers">prepared_buffers</link></member> <member><link linkend="beast.ref.prepared_buffers">prepared_buffers</link></member>
@@ -137,7 +138,6 @@
<member><link linkend="beast.ref.static_streambuf_n">static_streambuf_n</link></member> <member><link linkend="beast.ref.static_streambuf_n">static_streambuf_n</link></member>
<member><link linkend="beast.ref.static_string">static_string</link></member> <member><link linkend="beast.ref.static_string">static_string</link></member>
<member><link linkend="beast.ref.streambuf">streambuf</link></member> <member><link linkend="beast.ref.streambuf">streambuf</link></member>
<member><link linkend="beast.ref.streambuf_readstream">streambuf_readstream</link></member>
<member><link linkend="beast.ref.system_error">system_error</link></member> <member><link linkend="beast.ref.system_error">system_error</link></member>
</simplelist> </simplelist>
</entry> </entry>
@@ -164,8 +164,8 @@
<member><link linkend="beast.ref.is_BufferSequence">is_BufferSequence</link></member> <member><link linkend="beast.ref.is_BufferSequence">is_BufferSequence</link></member>
<member><link linkend="beast.ref.is_CompletionHandler">is_CompletionHandler</link></member> <member><link linkend="beast.ref.is_CompletionHandler">is_CompletionHandler</link></member>
<member><link linkend="beast.ref.is_ConstBufferSequence">is_ConstBufferSequence</link></member> <member><link linkend="beast.ref.is_ConstBufferSequence">is_ConstBufferSequence</link></member>
<member><link linkend="beast.ref.is_DynamicBuffer">is_DynamicBuffer</link></member>
<member><link linkend="beast.ref.is_MutableBufferSequence">is_MutableBufferSequence</link></member> <member><link linkend="beast.ref.is_MutableBufferSequence">is_MutableBufferSequence</link></member>
<member><link linkend="beast.ref.is_Streambuf">is_Streambuf</link></member>
<member><link linkend="beast.ref.is_SyncReadStream">is_SyncReadStream</link></member> <member><link linkend="beast.ref.is_SyncReadStream">is_SyncReadStream</link></member>
<member><link linkend="beast.ref.is_SyncStream">is_SyncStream</link></member> <member><link linkend="beast.ref.is_SyncStream">is_SyncStream</link></member>
<member><link linkend="beast.ref.is_SyncWriteStream">is_SyncWriteStream</link></member> <member><link linkend="beast.ref.is_SyncWriteStream">is_SyncWriteStream</link></member>
@@ -174,10 +174,10 @@
<entry valign="top"> <entry valign="top">
<bridgehead renderas="sect3">Concepts</bridgehead> <bridgehead renderas="sect3">Concepts</bridgehead>
<simplelist type="vert" columns="1"> <simplelist type="vert" columns="1">
<member><link linkend="beast.types.BufferSequence">BufferSequence</link></member>
<member><link linkend="beast.types.streams.AsyncStream">AsyncStream</link></member> <member><link linkend="beast.types.streams.AsyncStream">AsyncStream</link></member>
<member><link linkend="beast.types.BufferSequence">BufferSequence</link></member>
<member><link linkend="beast.types.DynamicBuffer">DynamicBuffer</link></member>
<member><link linkend="beast.types.streams.Stream">Stream</link></member> <member><link linkend="beast.types.streams.Stream">Stream</link></member>
<member><link linkend="beast.types.Streambuf">Streambuf</link></member>
<member><link linkend="beast.types.streams.SyncStream">SyncStream</link></member> <member><link linkend="beast.types.streams.SyncStream">SyncStream</link></member>
</simplelist> </simplelist>
</entry> </entry>

View File

@@ -1552,15 +1552,15 @@
<xsl:when test="declname = 'ConstBufferSequence' or type = 'class ConstBufferSequence'"> <xsl:when test="declname = 'ConstBufferSequence' or type = 'class ConstBufferSequence'">
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*ConstBufferSequence]]``</xsl:text> <xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*ConstBufferSequence]]``</xsl:text>
</xsl:when> </xsl:when>
<xsl:when test="declname = 'DynamicBuffer' or type = 'class DynamicBuffer'">
<xsl:text>class ``[link beast.types.DynamicBuffer [*DynamicBuffer]]``</xsl:text>
</xsl:when>
<xsl:when test="declname = 'MutableBufferSequence' or type = 'class MutableBufferSequence'"> <xsl:when test="declname = 'MutableBufferSequence' or type = 'class MutableBufferSequence'">
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/MutableBufferSequence.html [*MutableBufferSequence]]``</xsl:text> <xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/MutableBufferSequence.html [*MutableBufferSequence]]``</xsl:text>
</xsl:when> </xsl:when>
<xsl:when test="declname = 'Stream' or type = 'class Stream'"> <xsl:when test="declname = 'Stream' or type = 'class Stream'">
<xsl:text>class ``[link beast.types.streams.Stream [*Stream]]``</xsl:text> <xsl:text>class ``[link beast.types.streams.Stream [*Stream]]``</xsl:text>
</xsl:when> </xsl:when>
<xsl:when test="declname = 'Streambuf' or type = 'class Streambuf'">
<xsl:text>class ``[link beast.types.Streambuf [*Streambuf]]``</xsl:text>
</xsl:when>
<xsl:when test="type = 'class SyncStream'"> <xsl:when test="type = 'class SyncStream'">
<xsl:text>class ``[link beast.types.streams.SyncStream [*SyncStream]]``</xsl:text> <xsl:text>class ``[link beast.types.streams.SyncStream [*SyncStream]]``</xsl:text>
</xsl:when> </xsl:when>

125
doc/types/DynamicBuffer.qbk Normal file
View File

@@ -0,0 +1,125 @@
[/
Copyright (c) 2013-2016 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)
]
[section:DynamicBuffer DynamicBuffer]
A dynamic buffer encapsulates memory storage that may be automatically resized
as required, where the memory is divided into an input sequence followed by an
output sequence. These memory regions are internal to the dynamic buffer, but
direct access to the elements is provided to permit them to be efficiently used
with I/O operations, such as the send or receive operations of a socket. Data
written to the output sequence of a dynamic buffer object is appended to the
input sequence of the same object.
The interface to this concept is intended to permit the following
implementation strategies:
* A single contiguous octet array, which is reallocated as necessary to
accommodate changes in the size of the octet sequence.
* A sequence of one or more octet arrays, where each array is of the same
size. Additional octet array objects are appended to the sequence to
accommodate changes in the size of the octet sequence.
* A sequence of one or more octet arrays of varying sizes. Additional octet
array objects are appended to the sequence to accommodate changes in the
size of the character sequence. This is the implementation approached
currently offered by [link beast.ref.basic_streambuf `basic_streambuf`].
In the table below:
* `X` denotes a dynamic buffer class.
* `a` denotes a value of type `X`.
* `c` denotes a (possibly const) value of type `X`.
* `n` denotes a value of type `std::size_t`.
* `T` denotes a type meeting the requirements for [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/ConstBufferSequence.html `ConstBufferSequence`].
* `U` denotes a type meeting the requirements for [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/MutableBufferSequence.html `MutableBufferSequence`].
[table DynamicBuffer requirements
[[operation] [type] [semantics, pre/post-conditions]]
[
[`X::const_buffers_type`]
[`T`]
[
This type represents the memory associated with the input sequence.
]
]
[
[`X::mutable_buffers_type`]
[`U`]
[
This type represents the memory associated with the output sequence.
]
]
[
[`c.size()`]
[`std::size_t`]
[
Returns the size, in bytes, of the input sequence.
]
]
[
[`c.max_size()`]
[`std::size_t`]
[
Returns the permitted maximum of the sum of the sizes of the input
sequence and output sequence.
]
]
[
[`c.capacity()`]
[`std::size_t`]
[
Returns the maximum sum of the sizes of the input sequence and output
sequence that the dynamic buffer can hold without requiring reallocation.
]
]
[
[`c.data()`]
[`X::const_buffers_type`]
[
Returns a constant buffer sequence u that represents the memory
associated with the input sequence, and where `buffer_size(u) == size()`.
]
]
[
[`a.prepare(n)`]
[`X:mutable_buffers_type`]
[
Returns a mutable buffer sequence u representing the output sequence,
and where `buffer_size(u) == n`. The dynamic buffer reallocates memory
as required. All constant or mutable buffer sequences previously
obtained using `data()` or `prepare()` are invalidated.
Throws: `length_error` if `size() + n` exceeds `max_size()`.
]
]
[
[`a.commit(n)`]
[ ]
[
Appends `n` bytes from the start of the output sequence to the end of
the input sequence. The remainder of the output sequence is discarded.
If `n` is greater than the size of the output sequence, the entire
output sequence is appended to the input sequence. All constant or
mutable buffer sequences previously obtained using `data()` or
`prepare()` are invalidated.
]
]
[
[`a.consume(n)`]
[ ]
[
Removes `n` bytes from beginning of the input sequence. If `n` is
greater than the size of the input sequence, the entire input sequence
is removed. All constant or mutable buffer sequences previously
obtained using `data()` or `prepare()` are invalidated.
]
]
]
[endsect]

View File

@@ -1,96 +0,0 @@
[/
Copyright (c) 2013-2016 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)
]
[section:Streambuf Streambuf]
A [*`Streambuf`] represents a logical octet sequence divided in two sections,
the input sequence and the output sequence. Octets are written to the output
sequence, then moved to the input sequence where they are available for
reading. When some or all of the input sequence is no longer needed, it may
be consumed.
The interface to this concept is intended to permit the following
implementation strategies:
* A single contiguous octet array, which is reallocated as necessary to
accommodate changes in the size of the octet sequence.
* A sequence of one or more octet arrays, where each array is of the same
size. Additional octet array objects are appended to the sequence to
accommodate changes in the size of the octet sequence.
* A sequence of one or more octet arrays of varying sizes. Additional octet
array objects are appended to the sequence to accommodate changes in the
size of the character sequence. This is the implementation approached
currently offered by [link beast.ref.basic_streambuf `basic_streambuf`].
In the table below:
* `X` denotes a class meeting the requirements of [*`Streambuf`]
* `a` denotes a value of type `X`
* `n` denotes a value convertible to `std::size_t`
* `U`, `T` denote unspecified types.
[table Streambuf requirements
[[operation] [type] [semantics, pre/post-conditions]]
[
[`X::const_buffers_type`]
[`T`]
[`T` meets the requirements for [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/ConstBufferSequence.html `ConstBufferSequence`].]
]
[
[`X::mutable_buffers_type`]
[`U`]
[`U` meets the requirements for [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/MutableBufferSequence.html `MutableBufferSequence`].]
]
[
[`a.commit(n)`]
[`void`]
[Moves bytes from the output sequence to the input sequence.]
]
[
[`a.consume(n)`]
[`void`]
[Removes bytes from the input sequence.]
]
[
[`a.data()`]
[`T`]
[Returns a list of buffers that represents the input sequence.]
]
[
[`a.prepare(n)`]
[`U`]
[Returns a list of buffers that represents the output sequence, with
the given size.]
]
[
[`a.size()`]
[`std::size_t`]
[Returns the size of the input sequence.]
]
[
[`a.max_size()`]
[`std::size_t`]
[Returns the maximum size of the stream buffer.]
]
[
[`read_size_helper(a, n)`]
[`std::size_t`]
[
Returns the suggested number of bytes to read into the output
sequence where `n` is an upper limit on this value. One possible
implementation is to return the number of bytes that may be prepared
without causing a dynamic allocation or `n`, whichever is smaller.
Calls to `read_size_helper` will be made without namespace
qualification, to allow the rules for argument dependent lookup to
take effect.
]
]
]
[endsect]

View File

@@ -358,7 +358,7 @@ handler of the corresponding read function.]
Because calls to read data may return a variable amount of bytes, the Because calls to read data may return a variable amount of bytes, the
interface to calls that read data require an object that meets the requirements interface to calls that read data require an object that meets the requirements
of [link beast.types.Streambuf [*`Streambuf`]]. This concept is modeled on of [link beast.types.DynamicBuffer [*`DynamicBuffer`]]. This concept is modeled on
[@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/basic_streambuf.html `boost::asio::basic_streambuf`]. [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/basic_streambuf.html `boost::asio::basic_streambuf`].
The implementation does not perform queueing or buffering of messages. If The implementation does not perform queueing or buffering of messages. If

View File

@@ -24,8 +24,8 @@
#include <beast/core/static_string.hpp> #include <beast/core/static_string.hpp>
#include <beast/core/stream_concepts.hpp> #include <beast/core/stream_concepts.hpp>
#include <beast/core/streambuf.hpp> #include <beast/core/streambuf.hpp>
#include <beast/core/streambuf_readstream.hpp> #include <beast/core/dynabuf_readstream.hpp>
#include <beast/core/to_string.hpp> #include <beast/core/to_string.hpp>
#include <beast/core/write_streambuf.hpp> #include <beast/core/write_dynabuf.hpp>
#endif #endif

View File

@@ -18,14 +18,14 @@
namespace beast { namespace beast {
/** A @b `Streambuf` that uses multiple buffers internally. /** A @b `DynamicBuffer` that uses multiple buffers internally.
The implementation uses a sequence of one or more character arrays The implementation uses a sequence of one or more character arrays
of varying sizes. Additional character array objects are appended to of varying sizes. Additional character array objects are appended to
the sequence to accommodate changes in the size of the character the sequence to accommodate changes in the size of the character
sequence. sequence.
@note Meets the requirements of @b Streambuf. @note Meets the requirements of @b `DynamicBuffer`.
@tparam Allocator The allocator to use for managing memory. @tparam Allocator The allocator to use for managing memory.
*/ */
@@ -202,26 +202,37 @@ public:
basic_streambuf(std::size_t alloc_size = 1024, basic_streambuf(std::size_t alloc_size = 1024,
Allocator const& alloc = allocator_type{}); Allocator const& alloc = allocator_type{});
/// Get the associated allocator /// Returns a copy of the associated allocator.
allocator_type allocator_type
get_allocator() const get_allocator() const
{ {
return this->member(); return this->member();
} }
/// Get the maximum size of the basic_streambuf. /// Returns the size of the input sequence.
size_type
size() const
{
return in_size_;
}
/// Returns the permitted maximum sum of the sizes of the input and output sequence.
size_type size_type
max_size() const max_size() const
{ {
return std::numeric_limits<std::size_t>::max(); return std::numeric_limits<std::size_t>::max();
} }
/// Get the size of the input sequence. /// Returns the maximum sum of the sizes of the input sequence and output sequence the buffer can hold without requiring reallocation.
size_type std::size_t
size() const capacity() const;
{
return in_size_; /** Get a list of buffers that represents the input sequence.
}
@note These buffers remain valid across subsequent calls to `prepare`.
*/
const_buffers_type
data() const;
/** Get a list of buffers that represents the output sequence, with the given size. /** Get a list of buffers that represents the output sequence, with the given size.
@@ -239,22 +250,11 @@ public:
void void
commit(size_type n); commit(size_type n);
/** Get a list of buffers that represents the input sequence.
@note These buffers remain valid across subsequent calls to `prepare`.
*/
const_buffers_type
data() const;
/// Remove bytes from the input sequence. /// Remove bytes from the input sequence.
void void
consume(size_type n); consume(size_type n);
/// Clear everything. // Helper for boost::asio::read_until
void
clear();
// Helper for read_until
template<class OtherAllocator> template<class OtherAllocator>
friend friend
std::size_t std::size_t
@@ -262,6 +262,9 @@ public:
OtherAllocator> const& streambuf, std::size_t max_size); OtherAllocator> const& streambuf, std::size_t max_size);
private: private:
void
clear();
void void
move_assign(basic_streambuf& other, std::false_type); move_assign(basic_streambuf& other, std::false_type);
@@ -277,20 +280,17 @@ private:
void void
delete_list(); delete_list();
std::size_t
prepare_size() const;
void void
debug_check() const; debug_check() const;
}; };
/** Format output to a stream buffer. /** Format output to a @ref basic_streambuf.
@param streambuf The streambuf to write to. @param streambuf The @ref basic_streambuf to write to.
@param t The object to write. @param t The object to write.
@return The stream buffer. @return A reference to the @ref basic_streambuf.
*/ */
template<class Allocator, class T> template<class Allocator, class T>
basic_streambuf<Allocator>& basic_streambuf<Allocator>&

View File

@@ -35,6 +35,16 @@ struct is_ConstBufferSequence :
{ {
}; };
/// Determine if `T` meets the requirements of @b `DynamicBuffer`.
template<class T>
#if GENERATING_DOCS
struct is_DynamicBuffer : std::integral_constant<bool, ...>
#else
struct is_DynamicBuffer : detail::is_DynamicBuffer<T>::type
#endif
{
};
/// Determine if `T` meets the requirements of @b `MutableBufferSequence`. /// Determine if `T` meets the requirements of @b `MutableBufferSequence`.
template<class T> template<class T>
#if GENERATING_DOCS #if GENERATING_DOCS
@@ -46,16 +56,6 @@ struct is_MutableBufferSequence :
{ {
}; };
/// Determine if `T` meets the requirements of @b `Streambuf`.
template<class T>
#if GENERATING_DOCS
struct is_Streambuf : std::integral_constant<bool, ...>
#else
struct is_Streambuf : detail::is_Streambuf<T>::type
#endif
{
};
} // beast } // beast
#endif #endif

View File

@@ -86,7 +86,7 @@ public:
}; };
template<class T> template<class T>
class is_Streambuf class is_DynamicBuffer
{ {
template<class U, class R = std::integral_constant< template<class U, class R = std::integral_constant<
bool, is_BufferSequence<decltype( bool, is_BufferSequence<decltype(

View File

@@ -5,8 +5,8 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// //
#ifndef BEAST_DETAIL_WRITE_STREAMBUF_HPP #ifndef BEAST_DETAIL_WRITE_DYNABUF_HPP
#define BEAST_DETAIL_WRITE_STREAMBUF_HPP #define BEAST_DETAIL_WRITE_DYNABUF_HPP
#include <beast/core/buffer_concepts.hpp> #include <beast/core/buffer_concepts.hpp>
#include <boost/asio/buffer.hpp> #include <boost/asio/buffer.hpp>
@@ -42,73 +42,73 @@ public:
! is_string_literal<T>::value; ! is_string_literal<T>::value;
}; };
template<class Streambuf> template<class DynamicBuffer>
void void
write_streambuf(Streambuf& streambuf, write_dynabuf(DynamicBuffer& dynabuf,
boost::asio::const_buffer const& buffer) boost::asio::const_buffer const& buffer)
{ {
using boost::asio::buffer_copy; using boost::asio::buffer_copy;
using boost::asio::buffer_size; using boost::asio::buffer_size;
streambuf.commit(buffer_copy( dynabuf.commit(buffer_copy(
streambuf.prepare(buffer_size(buffer)), dynabuf.prepare(buffer_size(buffer)),
buffer)); buffer));
} }
template<class Streambuf> template<class DynamicBuffer>
void void
write_streambuf(Streambuf& streambuf, write_dynabuf(DynamicBuffer& dynabuf,
boost::asio::mutable_buffer const& buffer) boost::asio::mutable_buffer const& buffer)
{ {
using boost::asio::buffer_copy; using boost::asio::buffer_copy;
using boost::asio::buffer_size; using boost::asio::buffer_size;
streambuf.commit(buffer_copy( dynabuf.commit(buffer_copy(
streambuf.prepare(buffer_size(buffer)), dynabuf.prepare(buffer_size(buffer)),
buffer)); buffer));
} }
template<class Streambuf, class T> template<class DynamicBuffer, class T>
typename std::enable_if< typename std::enable_if<
is_BufferConvertible<T>::value && is_BufferConvertible<T>::value &&
! std::is_convertible<T, boost::asio::const_buffer>::value && ! std::is_convertible<T, boost::asio::const_buffer>::value &&
! std::is_convertible<T, boost::asio::mutable_buffer>::value ! std::is_convertible<T, boost::asio::mutable_buffer>::value
>::type >::type
write_streambuf(Streambuf& streambuf, T const& t) write_dynabuf(DynamicBuffer& dynabuf, T const& t)
{ {
using boost::asio::buffer_copy; using boost::asio::buffer_copy;
using boost::asio::buffer_size; using boost::asio::buffer_size;
auto const buffers = boost::asio::buffer(t); auto const buffers = boost::asio::buffer(t);
streambuf.commit(buffer_copy( dynabuf.commit(buffer_copy(
streambuf.prepare(buffer_size(buffers)), dynabuf.prepare(buffer_size(buffers)),
buffers)); buffers));
} }
template<class Streambuf, class Buffers> template<class DynamicBuffer, class Buffers>
typename std::enable_if< typename std::enable_if<
is_ConstBufferSequence<Buffers>::value && is_ConstBufferSequence<Buffers>::value &&
! is_BufferConvertible<Buffers>::value && ! is_BufferConvertible<Buffers>::value &&
! std::is_convertible<Buffers, boost::asio::const_buffer>::value && ! std::is_convertible<Buffers, boost::asio::const_buffer>::value &&
! std::is_convertible<Buffers, boost::asio::mutable_buffer>::value ! std::is_convertible<Buffers, boost::asio::mutable_buffer>::value
>::type >::type
write_streambuf(Streambuf& streambuf, Buffers const& buffers) write_dynabuf(DynamicBuffer& dynabuf, Buffers const& buffers)
{ {
using boost::asio::buffer_copy; using boost::asio::buffer_copy;
using boost::asio::buffer_size; using boost::asio::buffer_size;
streambuf.commit(buffer_copy( dynabuf.commit(buffer_copy(
streambuf.prepare(buffer_size(buffers)), dynabuf.prepare(buffer_size(buffers)),
buffers)); buffers));
} }
template<class Streambuf, std::size_t N> template<class DynamicBuffer, std::size_t N>
void void
write_streambuf(Streambuf& streambuf, const char (&s)[N]) write_dynabuf(DynamicBuffer& dynabuf, const char (&s)[N])
{ {
using boost::asio::buffer_copy; using boost::asio::buffer_copy;
streambuf.commit(buffer_copy( dynabuf.commit(buffer_copy(
streambuf.prepare(N - 1), dynabuf.prepare(N - 1),
boost::asio::buffer(s, N - 1))); boost::asio::buffer(s, N - 1)));
} }
template<class Streambuf, class T> template<class DynamicBuffer, class T>
typename std::enable_if< typename std::enable_if<
! is_string_literal<T>::value && ! is_string_literal<T>::value &&
! is_ConstBufferSequence<T>::value && ! is_ConstBufferSequence<T>::value &&
@@ -116,22 +116,22 @@ typename std::enable_if<
! std::is_convertible<T, boost::asio::const_buffer>::value && ! std::is_convertible<T, boost::asio::const_buffer>::value &&
! std::is_convertible<T, boost::asio::mutable_buffer>::value ! std::is_convertible<T, boost::asio::mutable_buffer>::value
>::type >::type
write_streambuf(Streambuf& streambuf, T const& t) write_dynabuf(DynamicBuffer& dynabuf, T const& t)
{ {
using boost::asio::buffer; using boost::asio::buffer;
using boost::asio::buffer_copy; using boost::asio::buffer_copy;
auto const s = boost::lexical_cast<std::string>(t); auto const s = boost::lexical_cast<std::string>(t);
streambuf.commit(buffer_copy( dynabuf.commit(buffer_copy(
streambuf.prepare(s.size()), buffer(s))); dynabuf.prepare(s.size()), buffer(s)));
} }
template<class Streambuf, class T0, class T1, class... TN> template<class DynamicBuffer, class T0, class T1, class... TN>
void void
write_streambuf(Streambuf& streambuf, write_dynabuf(DynamicBuffer& dynabuf,
T0 const& t0, T1 const& t1, TN const&... tn) T0 const& t0, T1 const& t1, TN const&... tn)
{ {
write_streambuf(streambuf, t0); write_dynabuf(dynabuf, t0);
write_streambuf(streambuf, t1, tn...); write_dynabuf(dynabuf, t1, tn...);
} }
} // detail } // detail

View File

@@ -5,8 +5,8 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// //
#ifndef BEAST_STREAMBUF_READSTREAM_HPP #ifndef BEAST_DYNABUF_READSTREAM_HPP
#define BEAST_STREAMBUF_READSTREAM_HPP #define BEAST_DYNABUF_READSTREAM_HPP
#include <beast/core/async_completion.hpp> #include <beast/core/async_completion.hpp>
#include <beast/core/buffer_concepts.hpp> #include <beast/core/buffer_concepts.hpp>
@@ -22,11 +22,11 @@
namespace beast { namespace beast {
/** A @b `Stream` with attached @b `Streambuf` to buffer reads. /** A @b `Stream` with attached @b `DynamicBuffer` to buffer reads.
This wraps a @b `Stream` implementation so that calls to write are This wraps a @b `Stream` implementation so that calls to write are
passed through to the underlying stream, while calls to read will passed through to the underlying stream, while calls to read will
first consume the input sequence stored in a @b `Streambuf` which first consume the input sequence stored in a @b `DynamicBuffer` which
is part of the object. is part of the object.
The use-case for this class is different than that of the The use-case for this class is different than that of the
@@ -50,9 +50,9 @@ namespace beast {
// Process the next HTTP headers on the stream, // Process the next HTTP headers on the stream,
// leaving excess bytes behind for the next call. // leaving excess bytes behind for the next call.
// //
template<class Streambuf> template<class DynamicBuffer>
void process_http_message( void process_http_message(
streambuf_readstream<Streambuf>& stream) dynabuf_readstream<DynamicBuffer>& stream)
{ {
// Read up to and including the end of the HTTP // Read up to and including the end of the HTTP
// headers, leaving the sequence in the stream's // headers, leaving the sequence in the stream's
@@ -85,24 +85,24 @@ namespace beast {
@tparam Stream The type of stream to wrap. @tparam Stream The type of stream to wrap.
@tparam Streambuf The type of stream buffer to use. @tparam DynamicBuffer The type of stream buffer to use.
*/ */
template<class Stream, class Streambuf> template<class Stream, class DynamicBuffer>
class streambuf_readstream class dynabuf_readstream
{ {
static_assert(is_Streambuf<Streambuf>::value, static_assert(is_DynamicBuffer<DynamicBuffer>::value,
"Streambuf requirements not met"); "DynamicBuffer requirements not met");
template<class Buffers, class Handler> template<class Buffers, class Handler>
class read_some_op; class read_some_op;
Streambuf sb_; DynamicBuffer sb_;
std::size_t capacity_ = 0; std::size_t capacity_ = 0;
Stream next_layer_; Stream next_layer_;
public: public:
/// The type of the internal buffer /// The type of the internal buffer
using streambuf_type = Streambuf; using dynabuf_type = DynamicBuffer;
/// The type of the next layer. /// The type of the next layer.
using next_layer_type = using next_layer_type =
@@ -122,14 +122,14 @@ public:
@note The behavior of move assignment on or from streams @note The behavior of move assignment on or from streams
with active or pending operations is undefined. with active or pending operations is undefined.
*/ */
streambuf_readstream(streambuf_readstream&&) = default; dynabuf_readstream(dynabuf_readstream&&) = default;
/** Move assignment. /** Move assignment.
@note The behavior of move assignment on or from streams @note The behavior of move assignment on or from streams
with active or pending operations is undefined. with active or pending operations is undefined.
*/ */
streambuf_readstream& operator=(streambuf_readstream&&) = default; dynabuf_readstream& operator=(dynabuf_readstream&&) = default;
/** Construct the wrapping stream. /** Construct the wrapping stream.
@@ -137,7 +137,7 @@ public:
*/ */
template<class... Args> template<class... Args>
explicit explicit
streambuf_readstream(Args&&... args); dynabuf_readstream(Args&&... args);
/// Get a reference to the next layer. /// Get a reference to the next layer.
next_layer_type& next_layer_type&
@@ -174,7 +174,7 @@ public:
by causing the internal buffer size to increase beyond by causing the internal buffer size to increase beyond
the caller defined maximum. the caller defined maximum.
*/ */
Streambuf& DynamicBuffer&
buffer() buffer()
{ {
return sb_; return sb_;
@@ -187,7 +187,7 @@ public:
by causing the internal buffer size to increase beyond by causing the internal buffer size to increase beyond
the caller defined maximum. the caller defined maximum.
*/ */
Streambuf const& DynamicBuffer const&
buffer() const buffer() const
{ {
return sb_; return sb_;
@@ -275,6 +275,6 @@ public:
} // beast } // beast
#include <beast/core/impl/streambuf_readstream.ipp> #include <beast/core/impl/dynabuf_readstream.ipp>
#endif #endif

View File

@@ -8,7 +8,7 @@
#ifndef BEAST_IMPL_BASIC_STREAMBUF_IPP #ifndef BEAST_IMPL_BASIC_STREAMBUF_IPP
#define BEAST_IMPL_BASIC_STREAMBUF_IPP #define BEAST_IMPL_BASIC_STREAMBUF_IPP
#include <beast/core/detail/write_streambuf.hpp> #include <beast/core/detail/write_dynabuf.hpp>
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <exception> #include <exception>
@@ -527,6 +527,28 @@ basic_streambuf<Allocator>::basic_streambuf(
"basic_streambuf: invalid alloc_size"); "basic_streambuf: invalid alloc_size");
} }
template<class Allocator>
std::size_t
basic_streambuf<Allocator>::capacity() const
{
auto pos = out_;
if(pos == list_.end())
return 0;
auto n = pos->size() - out_pos_;
while(++pos != list_.end())
n += pos->size();
return in_size_ + n;
}
template<class Allocator>
auto
basic_streambuf<Allocator>::
data() const ->
const_buffers_type
{
return const_buffers_type(*this);
}
template<class Allocator> template<class Allocator>
auto auto
basic_streambuf<Allocator>::prepare(size_type n) -> basic_streambuf<Allocator>::prepare(size_type n) ->
@@ -646,14 +668,6 @@ basic_streambuf<Allocator>::commit(size_type n)
debug_check(); debug_check();
} }
template<class Allocator>
auto
basic_streambuf<Allocator>::data() const ->
const_buffers_type
{
return const_buffers_type(*this);
}
template<class Allocator> template<class Allocator>
void void
basic_streambuf<Allocator>::consume(size_type n) basic_streambuf<Allocator>::consume(size_type n)
@@ -717,7 +731,8 @@ basic_streambuf<Allocator>::consume(size_type n)
template<class Allocator> template<class Allocator>
void void
basic_streambuf<Allocator>::clear() basic_streambuf<Allocator>::
clear()
{ {
delete_list(); delete_list();
list_.clear(); list_.clear();
@@ -795,21 +810,6 @@ basic_streambuf<Allocator>::delete_list()
} }
} }
// Returns the number of bytes which can be
// prepared without causing a memory allocation.
template<class Allocator>
std::size_t
basic_streambuf<Allocator>::prepare_size() const
{
auto pos = out_;
if(pos == list_.end())
return 0;
auto n = pos->size() - out_pos_;
while(++pos != list_.end())
n += pos->size();
return n;
}
template<class Allocator> template<class Allocator>
void void
basic_streambuf<Allocator>::debug_check() const basic_streambuf<Allocator>::debug_check() const
@@ -855,7 +855,7 @@ std::size_t
read_size_helper(basic_streambuf< read_size_helper(basic_streambuf<
Allocator> const& streambuf, std::size_t max_size) Allocator> const& streambuf, std::size_t max_size)
{ {
auto const avail = streambuf.prepare_size(); auto const avail = streambuf.capacity() - streambuf.size();
if(avail == 0) if(avail == 0)
return std::min(max_size, return std::min(max_size,
std::max<std::size_t>(512, streambuf.alloc_size_)); std::max<std::size_t>(512, streambuf.alloc_size_));
@@ -866,7 +866,7 @@ template<class Alloc, class T>
basic_streambuf<Alloc>& basic_streambuf<Alloc>&
operator<<(basic_streambuf<Alloc>& streambuf, T const& t) operator<<(basic_streambuf<Alloc>& streambuf, T const& t)
{ {
detail::write_streambuf(streambuf, t); detail::write_dynabuf(streambuf, t);
return streambuf; return streambuf;
} }

View File

@@ -5,8 +5,8 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// //
#ifndef BEAST_IMPL_STREAMBUF_READSTREAM_IPP #ifndef BEAST_IMPL_DYNABUF_READSTREAM_HPP
#define BEAST_IMPL_STREAMBUF_READSTREAM_IPP #define BEAST_IMPL_DYNABUF_READSTREAM_HPP
#include <beast/core/bind_handler.hpp> #include <beast/core/bind_handler.hpp>
#include <beast/core/handler_concepts.hpp> #include <beast/core/handler_concepts.hpp>
@@ -16,24 +16,24 @@
namespace beast { namespace beast {
template<class Stream, class Streambuf> template<class Stream, class DynamicBuffer>
template<class MutableBufferSequence, class Handler> template<class MutableBufferSequence, class Handler>
class streambuf_readstream< class dynabuf_readstream<
Stream, Streambuf>::read_some_op Stream, DynamicBuffer>::read_some_op
{ {
using alloc_type = using alloc_type =
handler_alloc<char, Handler>; handler_alloc<char, Handler>;
struct data struct data
{ {
streambuf_readstream& srs; dynabuf_readstream& srs;
MutableBufferSequence bs; MutableBufferSequence bs;
Handler h; Handler h;
int state = 0; int state = 0;
template<class DeducedHandler> template<class DeducedHandler>
data(DeducedHandler&& h_, data(DeducedHandler&& h_,
streambuf_readstream& srs_, dynabuf_readstream& srs_,
MutableBufferSequence const& bs_) MutableBufferSequence const& bs_)
: srs(srs_) : srs(srs_)
, bs(bs_) , bs(bs_)
@@ -50,7 +50,7 @@ public:
template<class DeducedHandler, class... Args> template<class DeducedHandler, class... Args>
read_some_op(DeducedHandler&& h, read_some_op(DeducedHandler&& h,
streambuf_readstream& srs, Args&&... args) dynabuf_readstream& srs, Args&&... args)
: d_(std::allocate_shared<data>(alloc_type{h}, : d_(std::allocate_shared<data>(alloc_type{h},
std::forward<DeducedHandler>(h), srs, std::forward<DeducedHandler>(h), srs,
std::forward<Args>(args)...)) std::forward<Args>(args)...))
@@ -94,10 +94,10 @@ public:
} }
}; };
template<class Stream, class Streambuf> template<class Stream, class DynamicBuffer>
template<class MutableBufferSequence, class Handler> template<class MutableBufferSequence, class Handler>
void void
streambuf_readstream<Stream, Streambuf>:: dynabuf_readstream<Stream, DynamicBuffer>::
read_some_op<MutableBufferSequence, Handler>::operator()( read_some_op<MutableBufferSequence, Handler>::operator()(
error_code const& ec, std::size_t bytes_transferred) error_code const& ec, std::size_t bytes_transferred)
{ {
@@ -155,18 +155,18 @@ read_some_op<MutableBufferSequence, Handler>::operator()(
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<class Stream, class Streambuf> template<class Stream, class DynamicBuffer>
template<class... Args> template<class... Args>
streambuf_readstream<Stream, Streambuf>:: dynabuf_readstream<Stream, DynamicBuffer>::
streambuf_readstream(Args&&... args) dynabuf_readstream(Args&&... args)
: next_layer_(std::forward<Args>(args)...) : next_layer_(std::forward<Args>(args)...)
{ {
} }
template<class Stream, class Streambuf> template<class Stream, class DynamicBuffer>
template<class ConstBufferSequence, class WriteHandler> template<class ConstBufferSequence, class WriteHandler>
auto auto
streambuf_readstream<Stream, Streambuf>:: dynabuf_readstream<Stream, DynamicBuffer>::
async_write_some(ConstBufferSequence const& buffers, async_write_some(ConstBufferSequence const& buffers,
WriteHandler&& handler) -> WriteHandler&& handler) ->
typename async_completion< typename async_completion<
@@ -184,10 +184,10 @@ async_write_some(ConstBufferSequence const& buffers,
std::forward<WriteHandler>(handler)); std::forward<WriteHandler>(handler));
} }
template<class Stream, class Streambuf> template<class Stream, class DynamicBuffer>
template<class MutableBufferSequence> template<class MutableBufferSequence>
std::size_t std::size_t
streambuf_readstream<Stream, Streambuf>:: dynabuf_readstream<Stream, DynamicBuffer>::
read_some( read_some(
MutableBufferSequence const& buffers) MutableBufferSequence const& buffers)
{ {
@@ -203,10 +203,10 @@ read_some(
return n; return n;
} }
template<class Stream, class Streambuf> template<class Stream, class DynamicBuffer>
template<class MutableBufferSequence> template<class MutableBufferSequence>
std::size_t std::size_t
streambuf_readstream<Stream, Streambuf>:: dynabuf_readstream<Stream, DynamicBuffer>::
read_some(MutableBufferSequence const& buffers, read_some(MutableBufferSequence const& buffers,
error_code& ec) error_code& ec)
{ {
@@ -232,10 +232,10 @@ read_some(MutableBufferSequence const& buffers,
return bytes_transferred; return bytes_transferred;
} }
template<class Stream, class Streambuf> template<class Stream, class DynamicBuffer>
template<class MutableBufferSequence, class ReadHandler> template<class MutableBufferSequence, class ReadHandler>
auto auto
streambuf_readstream<Stream, Streambuf>:: dynabuf_readstream<Stream, DynamicBuffer>::
async_read_some( async_read_some(
MutableBufferSequence const& buffers, MutableBufferSequence const& buffers,
ReadHandler&& handler) -> ReadHandler&& handler) ->

View File

@@ -15,7 +15,7 @@
namespace beast { namespace beast {
/** A @b `Streambuf` with a fixed size internal buffer. /** A @b `DynamicBuffer` with a fixed size internal buffer.
Ownership of the underlying storage belongs to the derived class. Ownership of the underlying storage belongs to the derived class.

View File

@@ -5,20 +5,20 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// //
#ifndef BEAST_WRITE_STREAMBUF_HPP #ifndef BEAST_WRITE_DYNABUF_HPP
#define BEAST_WRITE_STREAMBUF_HPP #define BEAST_WRITE_DYNABUF_HPP
#include <beast/core/buffer_concepts.hpp> #include <beast/core/buffer_concepts.hpp>
#include <beast/core/detail/write_streambuf.hpp> #include <beast/core/detail/write_dynabuf.hpp>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
namespace beast { namespace beast {
/** Write to a Streambuf. /** Write to a @b `DynamicBuffer`.
This function appends the serialized representation of each provided This function appends the serialized representation of each provided
argument into the stream buffer. It is capable of converting the argument into the dynamic buffer. It is capable of converting the
following types of arguments: following types of arguments:
@li `boost::asio::const_buffer` @li `boost::asio::const_buffer`
@@ -33,29 +33,29 @@ namespace beast {
For all types not listed above, the function will invoke For all types not listed above, the function will invoke
`boost::lexical_cast` on the argument in an attempt to convert to `boost::lexical_cast` on the argument in an attempt to convert to
a string, which is then appended to the stream buffer. a string, which is then appended to the dynamic buffer.
When this function serializes numbers, it converts them to When this function serializes numbers, it converts them to
their text representation as if by a call to `std::to_string`. their text representation as if by a call to `std::to_string`.
@param streambuf The stream buffer to write to. @param dynabuf The dynamic buffer to write to.
@param args A list of one or more arguments to write. @param args A list of one or more arguments to write.
@throws unspecified Any exceptions thrown by `boost::lexical_cast`. @throws unspecified Any exceptions thrown by `boost::lexical_cast`.
@note This function participates in overload resolution only if @note This function participates in overload resolution only if
the `streambuf` parameter meets the requirements of @b `Streambuf`. the `dynabuf` parameter meets the requirements of @b `DynamicBuffer`.
*/ */
template<class Streambuf, class... Args> template<class DynamicBuffer, class... Args>
#if GENERATING_DOCS #if GENERATING_DOCS
void void
#else #else
typename std::enable_if<is_Streambuf<Streambuf>::value>::type typename std::enable_if<is_DynamicBuffer<DynamicBuffer>::value>::type
#endif #endif
write(Streambuf& streambuf, Args const&... args) write(DynamicBuffer& dynabuf, Args const&... args)
{ {
detail::write_streambuf(streambuf, args...); detail::write_dynabuf(dynabuf, args...);
} }
} // beast } // beast

View File

@@ -0,0 +1,95 @@
//
// Copyright (c) 2013-2016 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_HTTP_BASIC_DYNABUF_BODY_HPP
#define BEAST_HTTP_BASIC_DYNABUF_BODY_HPP
#include <beast/http/body_type.hpp>
#include <boost/asio/buffer.hpp>
namespace beast {
namespace http {
/** A message body represented by a @b `DynamicBuffer`
Meets the requirements of @b `Body`.
*/
template<class DynamicBuffer>
struct basic_dynabuf_body
{
/// The type of the `message::body` member
using value_type = DynamicBuffer;
#if GENERATING_DOCS
private:
#endif
class reader
{
value_type& sb_;
public:
template<bool isRequest, class Headers>
explicit
reader(message<isRequest,
basic_dynabuf_body, Headers>& m) noexcept
: sb_(m.body)
{
}
void
write(void const* data,
std::size_t size, error_code&) noexcept
{
using boost::asio::buffer;
using boost::asio::buffer_copy;
sb_.commit(buffer_copy(
sb_.prepare(size), buffer(data, size)));
}
};
class writer
{
DynamicBuffer const& body_;
public:
writer(writer const&) = delete;
writer& operator=(writer const&) = delete;
template<bool isRequest, class Headers>
explicit
writer(message<
isRequest, basic_dynabuf_body, Headers> const& m)
: body_(m.body)
{
}
void
init(error_code& ec)
{
}
std::uint64_t
content_length() const
{
return body_.size();
}
template<class Write>
boost::tribool
operator()(resume_context&&, error_code&, Write&& write)
{
write(body_.data());
return true;
}
};
};
} // http
} // beast
#endif

View File

@@ -9,7 +9,6 @@
#define BEAST_HTTP_EMPTY_BODY_HPP #define BEAST_HTTP_EMPTY_BODY_HPP
#include <beast/http/body_type.hpp> #include <beast/http/body_type.hpp>
#include <beast/core/streambuf.hpp>
#include <boost/asio/buffer.hpp> #include <boost/asio/buffer.hpp>
#include <memory> #include <memory>
#include <string> #include <string>

View File

@@ -21,7 +21,7 @@ namespace http {
namespace detail { namespace detail {
template<class Stream, template<class Stream,
class Streambuf, class Parser, class Handler> class DynamicBuffer, class Parser, class Handler>
class parse_op class parse_op
{ {
using alloc_type = using alloc_type =
@@ -30,7 +30,7 @@ class parse_op
struct data struct data
{ {
Stream& s; Stream& s;
Streambuf& sb; DynamicBuffer& db;
Parser& p; Parser& p;
Handler h; Handler h;
bool started = false; bool started = false;
@@ -39,9 +39,9 @@ class parse_op
template<class DeducedHandler> template<class DeducedHandler>
data(DeducedHandler&& h_, Stream& s_, data(DeducedHandler&& h_, Stream& s_,
Streambuf& sb_, Parser& p_) DynamicBuffer& sb_, Parser& p_)
: s(s_) : s(s_)
, sb(sb_) , db(sb_)
, p(p_) , p(p_)
, h(std::forward<DeducedHandler>(h_)) , h(std::forward<DeducedHandler>(h_))
, cont(boost_asio_handler_cont_helpers:: , cont(boost_asio_handler_cont_helpers::
@@ -101,9 +101,9 @@ public:
}; };
template<class Stream, template<class Stream,
class Streambuf, class Parser, class Handler> class DynamicBuffer, class Parser, class Handler>
void void
parse_op<Stream, Streambuf, Parser, Handler>:: parse_op<Stream, DynamicBuffer, Parser, Handler>::
operator()(error_code ec, std::size_t bytes_transferred, bool again) operator()(error_code ec, std::size_t bytes_transferred, bool again)
{ {
auto& d = *d_; auto& d = *d_;
@@ -115,7 +115,7 @@ operator()(error_code ec, std::size_t bytes_transferred, bool again)
case 0: case 0:
{ {
auto const used = auto const used =
d.p.write(d.sb.data(), ec); d.p.write(d.db.data(), ec);
if(ec) if(ec)
{ {
// call handler // call handler
@@ -126,7 +126,7 @@ operator()(error_code ec, std::size_t bytes_transferred, bool again)
} }
if(used > 0) if(used > 0)
d.started = true; d.started = true;
d.sb.consume(used); d.db.consume(used);
if(d.p.complete()) if(d.p.complete())
{ {
// call handler // call handler
@@ -142,8 +142,8 @@ operator()(error_code ec, std::size_t bytes_transferred, bool again)
case 1: case 1:
// read // read
d.state = 2; d.state = 2;
d.s.async_read_some(d.sb.prepare( d.s.async_read_some(d.db.prepare(
read_size_helper(d.sb, 65536)), read_size_helper(d.db, 65536)),
std::move(*this)); std::move(*this));
return; return;
@@ -172,8 +172,8 @@ operator()(error_code ec, std::size_t bytes_transferred, bool again)
d.state = 99; d.state = 99;
break; break;
} }
d.sb.commit(bytes_transferred); d.db.commit(bytes_transferred);
auto const used = d.p.write(d.sb.data(), ec); auto const used = d.p.write(d.db.data(), ec);
if(ec) if(ec)
{ {
// call handler // call handler
@@ -182,7 +182,7 @@ operator()(error_code ec, std::size_t bytes_transferred, bool again)
} }
if(used > 0) if(used > 0)
d.started = true; d.started = true;
d.sb.consume(used); d.db.consume(used);
if(d.p.complete()) if(d.p.complete())
{ {
// call handler // call handler
@@ -199,7 +199,7 @@ operator()(error_code ec, std::size_t bytes_transferred, bool again)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<class Stream, class Streambuf, template<class Stream, class DynamicBuffer,
bool isRequest, class Body, class Headers, bool isRequest, class Body, class Headers,
class Handler> class Handler>
class read_op class read_op
@@ -216,7 +216,7 @@ class read_op
struct data struct data
{ {
Stream& s; Stream& s;
Streambuf& sb; DynamicBuffer& db;
message_type& m; message_type& m;
parser_type p; parser_type p;
Handler h; Handler h;
@@ -226,9 +226,9 @@ class read_op
template<class DeducedHandler> template<class DeducedHandler>
data(DeducedHandler&& h_, Stream& s_, data(DeducedHandler&& h_, Stream& s_,
Streambuf& sb_, message_type& m_) DynamicBuffer& sb_, message_type& m_)
: s(s_) : s(s_)
, sb(sb_) , db(sb_)
, m(m_) , m(m_)
, h(std::forward<DeducedHandler>(h_)) , h(std::forward<DeducedHandler>(h_))
, cont(boost_asio_handler_cont_helpers:: , cont(boost_asio_handler_cont_helpers::
@@ -286,11 +286,11 @@ public:
} }
}; };
template<class Stream, class Streambuf, template<class Stream, class DynamicBuffer,
bool isRequest, class Body, class Headers, bool isRequest, class Body, class Headers,
class Handler> class Handler>
void void
read_op<Stream, Streambuf, isRequest, Body, Headers, Handler>:: read_op<Stream, DynamicBuffer, isRequest, Body, Headers, Handler>::
operator()(error_code ec, bool again) operator()(error_code ec, bool again)
{ {
auto& d = *d_; auto& d = *d_;
@@ -301,7 +301,7 @@ operator()(error_code ec, bool again)
{ {
case 0: case 0:
d.state = 1; d.state = 1;
async_parse(d.s, d.sb, d.p, std::move(*this)); async_parse(d.s, d.db, d.p, std::move(*this));
return; return;
case 1: case 1:
@@ -318,49 +318,49 @@ operator()(error_code ec, bool again)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<class SyncReadStream, class Streambuf, class Parser> template<class SyncReadStream, class DynamicBuffer, class Parser>
void void
parse(SyncReadStream& stream, parse(SyncReadStream& stream,
Streambuf& streambuf, Parser& parser) DynamicBuffer& dynabuf, Parser& parser)
{ {
static_assert(is_SyncReadStream<SyncReadStream>::value, static_assert(is_SyncReadStream<SyncReadStream>::value,
"SyncReadStream requirements not met"); "SyncReadStream requirements not met");
static_assert(is_Streambuf<Streambuf>::value, static_assert(is_DynamicBuffer<DynamicBuffer>::value,
"Streambuf requirements not met"); "DynamicBuffer requirements not met");
static_assert(is_Parser<Parser>::value, static_assert(is_Parser<Parser>::value,
"Parser requirements not met"); "Parser requirements not met");
error_code ec; error_code ec;
parse(stream, streambuf, parser, ec); parse(stream, dynabuf, parser, ec);
if(ec) if(ec)
throw boost::system::system_error{ec}; throw boost::system::system_error{ec};
} }
template<class SyncReadStream, class Streambuf, class Parser> template<class SyncReadStream, class DynamicBuffer, class Parser>
void void
parse(SyncReadStream& stream, Streambuf& streambuf, parse(SyncReadStream& stream, DynamicBuffer& dynabuf,
Parser& parser, error_code& ec) Parser& parser, error_code& ec)
{ {
static_assert(is_SyncReadStream<SyncReadStream>::value, static_assert(is_SyncReadStream<SyncReadStream>::value,
"SyncReadStream requirements not met"); "SyncReadStream requirements not met");
static_assert(is_Streambuf<Streambuf>::value, static_assert(is_DynamicBuffer<DynamicBuffer>::value,
"Streambuf requirements not met"); "DynamicBuffer requirements not met");
static_assert(is_Parser<Parser>::value, static_assert(is_Parser<Parser>::value,
"Parser requirements not met"); "Parser requirements not met");
bool started = false; bool started = false;
for(;;) for(;;)
{ {
auto used = auto used =
parser.write(streambuf.data(), ec); parser.write(dynabuf.data(), ec);
if(ec) if(ec)
return; return;
streambuf.consume(used); dynabuf.consume(used);
if(used > 0) if(used > 0)
started = true; started = true;
if(parser.complete()) if(parser.complete())
break; break;
streambuf.commit(stream.read_some( dynabuf.commit(stream.read_some(
streambuf.prepare(read_size_helper( dynabuf.prepare(read_size_helper(
streambuf, 65536)), ec)); dynabuf, 65536)), ec));
if(ec && ec != boost::asio::error::eof) if(ec && ec != boost::asio::error::eof)
return; return;
if(ec == boost::asio::error::eof) if(ec == boost::asio::error::eof)
@@ -379,86 +379,86 @@ parse(SyncReadStream& stream, Streambuf& streambuf,
} }
template<class AsyncReadStream, template<class AsyncReadStream,
class Streambuf, class Parser, class ReadHandler> class DynamicBuffer, class Parser, class ReadHandler>
typename async_completion< typename async_completion<
ReadHandler, void(error_code)>::result_type ReadHandler, void(error_code)>::result_type
async_parse(AsyncReadStream& stream, async_parse(AsyncReadStream& stream,
Streambuf& streambuf, Parser& parser, ReadHandler&& handler) DynamicBuffer& dynabuf, Parser& parser, ReadHandler&& handler)
{ {
static_assert(is_AsyncReadStream<AsyncReadStream>::value, static_assert(is_AsyncReadStream<AsyncReadStream>::value,
"AsyncReadStream requirements not met"); "AsyncReadStream requirements not met");
static_assert(is_Streambuf<Streambuf>::value, static_assert(is_DynamicBuffer<DynamicBuffer>::value,
"Streambuf requirements not met"); "DynamicBuffer requirements not met");
static_assert(is_Parser<Parser>::value, static_assert(is_Parser<Parser>::value,
"Parser requirements not met"); "Parser requirements not met");
beast::async_completion<ReadHandler, beast::async_completion<ReadHandler,
void(error_code)> completion(handler); void(error_code)> completion(handler);
detail::parse_op<AsyncReadStream, Streambuf, detail::parse_op<AsyncReadStream, DynamicBuffer,
Parser, decltype(completion.handler)>{ Parser, decltype(completion.handler)>{
completion.handler, stream, streambuf, parser}; completion.handler, stream, dynabuf, parser};
return completion.result.get(); return completion.result.get();
} }
template<class SyncReadStream, class Streambuf, template<class SyncReadStream, class DynamicBuffer,
bool isRequest, class Body, class Headers> bool isRequest, class Body, class Headers>
void void
read(SyncReadStream& stream, Streambuf& streambuf, read(SyncReadStream& stream, DynamicBuffer& dynabuf,
message_v1<isRequest, Body, Headers>& msg) message_v1<isRequest, Body, Headers>& msg)
{ {
static_assert(is_SyncReadStream<SyncReadStream>::value, static_assert(is_SyncReadStream<SyncReadStream>::value,
"SyncReadStream requirements not met"); "SyncReadStream requirements not met");
static_assert(is_Streambuf<Streambuf>::value, static_assert(is_DynamicBuffer<DynamicBuffer>::value,
"Streambuf requirements not met"); "DynamicBuffer requirements not met");
static_assert(is_ReadableBody<Body>::value, static_assert(is_ReadableBody<Body>::value,
"ReadableBody requirements not met"); "ReadableBody requirements not met");
error_code ec; error_code ec;
read(stream, streambuf, msg, ec); read(stream, dynabuf, msg, ec);
if(ec) if(ec)
throw system_error{ec}; throw system_error{ec};
} }
template<class SyncReadStream, class Streambuf, template<class SyncReadStream, class DynamicBuffer,
bool isRequest, class Body, class Headers> bool isRequest, class Body, class Headers>
void void
read(SyncReadStream& stream, Streambuf& streambuf, read(SyncReadStream& stream, DynamicBuffer& dynabuf,
message_v1<isRequest, Body, Headers>& m, message_v1<isRequest, Body, Headers>& m,
error_code& ec) error_code& ec)
{ {
static_assert(is_SyncReadStream<SyncReadStream>::value, static_assert(is_SyncReadStream<SyncReadStream>::value,
"SyncReadStream requirements not met"); "SyncReadStream requirements not met");
static_assert(is_Streambuf<Streambuf>::value, static_assert(is_DynamicBuffer<DynamicBuffer>::value,
"Streambuf requirements not met"); "DynamicBuffer requirements not met");
static_assert(is_ReadableBody<Body>::value, static_assert(is_ReadableBody<Body>::value,
"ReadableBody requirements not met"); "ReadableBody requirements not met");
parser_v1<isRequest, Body, Headers> p; parser_v1<isRequest, Body, Headers> p;
parse(stream, streambuf, p, ec); parse(stream, dynabuf, p, ec);
if(ec) if(ec)
return; return;
assert(p.complete()); assert(p.complete());
m = p.release(); m = p.release();
} }
template<class AsyncReadStream, class Streambuf, template<class AsyncReadStream, class DynamicBuffer,
bool isRequest, class Body, class Headers, bool isRequest, class Body, class Headers,
class ReadHandler> class ReadHandler>
typename async_completion< typename async_completion<
ReadHandler, void(error_code)>::result_type ReadHandler, void(error_code)>::result_type
async_read(AsyncReadStream& stream, Streambuf& streambuf, async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf,
message_v1<isRequest, Body, Headers>& m, message_v1<isRequest, Body, Headers>& m,
ReadHandler&& handler) ReadHandler&& handler)
{ {
static_assert(is_AsyncReadStream<AsyncReadStream>::value, static_assert(is_AsyncReadStream<AsyncReadStream>::value,
"AsyncReadStream requirements not met"); "AsyncReadStream requirements not met");
static_assert(is_Streambuf<Streambuf>::value, static_assert(is_DynamicBuffer<DynamicBuffer>::value,
"Streambuf requirements not met"); "DynamicBuffer requirements not met");
static_assert(is_ReadableBody<Body>::value, static_assert(is_ReadableBody<Body>::value,
"ReadableBody requirements not met"); "ReadableBody requirements not met");
beast::async_completion<ReadHandler, beast::async_completion<ReadHandler,
void(error_code)> completion(handler); void(error_code)> completion(handler);
detail::read_op<AsyncReadStream, Streambuf, detail::read_op<AsyncReadStream, DynamicBuffer,
isRequest, Body, Headers, decltype( isRequest, Body, Headers, decltype(
completion.handler)>{completion.handler, completion.handler)>{completion.handler,
stream, streambuf, m}; stream, dynabuf, m};
return completion.result.get(); return completion.result.get();
} }

View File

@@ -18,7 +18,7 @@
#include <beast/core/handler_alloc.hpp> #include <beast/core/handler_alloc.hpp>
#include <beast/core/stream_concepts.hpp> #include <beast/core/stream_concepts.hpp>
#include <beast/core/streambuf.hpp> #include <beast/core/streambuf.hpp>
#include <beast/core/write_streambuf.hpp> #include <beast/core/write_dynabuf.hpp>
#include <boost/asio/write.hpp> #include <boost/asio/write.hpp>
#include <boost/logic/tribool.hpp> #include <boost/logic/tribool.hpp>
#include <condition_variable> #include <condition_variable>
@@ -32,51 +32,51 @@ namespace http {
namespace detail { namespace detail {
template<class Streambuf, class Body, class Headers> template<class DynamicBuffer, class Body, class Headers>
void void
write_firstline(Streambuf& streambuf, write_firstline(DynamicBuffer& dynabuf,
message_v1<true, Body, Headers> const& msg) message_v1<true, Body, Headers> const& msg)
{ {
write(streambuf, msg.method); write(dynabuf, msg.method);
write(streambuf, " "); write(dynabuf, " ");
write(streambuf, msg.url); write(dynabuf, msg.url);
write(streambuf, " HTTP/"); write(dynabuf, " HTTP/");
write(streambuf, msg.version / 10); write(dynabuf, msg.version / 10);
write(streambuf, "."); write(dynabuf, ".");
write(streambuf, msg.version % 10); write(dynabuf, msg.version % 10);
write(streambuf, "\r\n"); write(dynabuf, "\r\n");
} }
template<class Streambuf, class Body, class Headers> template<class DynamicBuffer, class Body, class Headers>
void void
write_firstline(Streambuf& streambuf, write_firstline(DynamicBuffer& dynabuf,
message_v1<false, Body, Headers> const& msg) message_v1<false, Body, Headers> const& msg)
{ {
write(streambuf, "HTTP/"); write(dynabuf, "HTTP/");
write(streambuf, msg.version / 10); write(dynabuf, msg.version / 10);
write(streambuf, "."); write(dynabuf, ".");
write(streambuf, msg.version % 10); write(dynabuf, msg.version % 10);
write(streambuf, " "); write(dynabuf, " ");
write(streambuf, msg.status); write(dynabuf, msg.status);
write(streambuf, " "); write(dynabuf, " ");
write(streambuf, msg.reason); write(dynabuf, msg.reason);
write(streambuf, "\r\n"); write(dynabuf, "\r\n");
} }
template<class Streambuf, class FieldSequence> template<class DynamicBuffer, class FieldSequence>
void void
write_fields(Streambuf& streambuf, FieldSequence const& fields) write_fields(DynamicBuffer& dynabuf, FieldSequence const& fields)
{ {
static_assert(is_Streambuf<Streambuf>::value, static_assert(is_DynamicBuffer<DynamicBuffer>::value,
"Streambuf requirements not met"); "DynamicBuffer requirements not met");
//static_assert(is_FieldSequence<FieldSequence>::value, //static_assert(is_FieldSequence<FieldSequence>::value,
// "FieldSequence requirements not met"); // "FieldSequence requirements not met");
for(auto const& field : fields) for(auto const& field : fields)
{ {
write(streambuf, field.name()); write(dynabuf, field.name());
write(streambuf, ": "); write(dynabuf, ": ");
write(streambuf, field.value()); write(dynabuf, field.value());
write(streambuf, "\r\n"); write(dynabuf, "\r\n");
} }
} }
@@ -378,17 +378,17 @@ operator()(error_code ec, std::size_t, bool again)
d.copy = {}; d.copy = {};
} }
template<class SyncWriteStream, class Streambuf> template<class SyncWriteStream, class DynamicBuffer>
class writef0_lambda class writef0_lambda
{ {
Streambuf const& sb_; DynamicBuffer const& sb_;
SyncWriteStream& stream_; SyncWriteStream& stream_;
bool chunked_; bool chunked_;
error_code& ec_; error_code& ec_;
public: public:
writef0_lambda(SyncWriteStream& stream, writef0_lambda(SyncWriteStream& stream,
Streambuf const& sb, bool chunked, error_code& ec) DynamicBuffer const& sb, bool chunked, error_code& ec)
: sb_(sb) : sb_(sb)
, stream_(stream) , stream_(stream)
, chunked_(chunked) , chunked_(chunked)
@@ -548,9 +548,8 @@ async_write(AsyncWriteStream& stream,
message_v1<isRequest, Body, Headers> const& msg, message_v1<isRequest, Body, Headers> const& msg,
WriteHandler&& handler) WriteHandler&& handler)
{ {
static_assert( static_assert(is_AsyncWriteStream<AsyncWriteStream>::value,
is_AsyncWriteStream<AsyncWriteStream>::value, "AsyncWriteStream requirements not met");
"AsyncWriteStream requirements not met");
static_assert(is_WritableBody<Body>::value, static_assert(is_WritableBody<Body>::value,
"WritableBody requirements not met"); "WritableBody requirements not met");
beast::async_completion<WriteHandler, beast::async_completion<WriteHandler,

View File

@@ -12,7 +12,6 @@
#include <beast/core/error.hpp> #include <beast/core/error.hpp>
#include <beast/core/async_completion.hpp> #include <beast/core/async_completion.hpp>
#include <boost/asio/buffer.hpp> #include <boost/asio/buffer.hpp>
#include <boost/system/error_code.hpp>
namespace beast { namespace beast {
namespace http { namespace http {
@@ -36,7 +35,7 @@ namespace http {
@param stream The stream from which the data is to be read. @param stream The stream from which the data is to be read.
The type must support the @b `SyncReadStream` concept. The type must support the @b `SyncReadStream` concept.
@param streambuf A `Streambuf` holding additional bytes @param dynabuf A @b `DynamicBuffer` holding additional bytes
read by the implementation from the stream. This is both read by the implementation from the stream. This is both
an input and an output parameter; on entry, any data in the an input and an output parameter; on entry, any data in the
stream buffer's input sequence will be given to the parser stream buffer's input sequence will be given to the parser
@@ -47,10 +46,10 @@ namespace http {
@throws boost::system::system_error on failure. @throws boost::system::system_error on failure.
*/ */
template<class SyncReadStream, class Streambuf, class Parser> template<class SyncReadStream, class DynamicBuffer, class Parser>
void void
parse(SyncReadStream& stream, parse(SyncReadStream& stream,
Streambuf& streambuf, Parser& parser); DynamicBuffer& dynabuf, Parser& parser);
/** Parse a HTTP/1 message from a stream. /** Parse a HTTP/1 message from a stream.
@@ -71,7 +70,7 @@ parse(SyncReadStream& stream,
@param stream The stream from which the data is to be read. @param stream The stream from which the data is to be read.
The type must support the @b `SyncReadStream` concept. The type must support the @b `SyncReadStream` concept.
@param streambuf A `Streambuf` holding additional bytes @param dynabuf A @b `DynamicBuffer` holding additional bytes
read by the implementation from the stream. This is both read by the implementation from the stream. This is both
an input and an output parameter; on entry, any data in the an input and an output parameter; on entry, any data in the
stream buffer's input sequence will be given to the parser stream buffer's input sequence will be given to the parser
@@ -82,10 +81,10 @@ parse(SyncReadStream& stream,
@param ec Set to the error, if any occurred. @param ec Set to the error, if any occurred.
*/ */
template<class SyncReadStream, class Streambuf, class Parser> template<class SyncReadStream, class DynamicBuffer, class Parser>
void void
parse(SyncReadStream& stream, parse(SyncReadStream& stream,
Streambuf& streambuf, Parser& parser, error_code& ec); DynamicBuffer& dynabuf, Parser& parser, error_code& ec);
/** Start an asynchronous operation to parse a HTTP/1 message from a stream. /** Start an asynchronous operation to parse a HTTP/1 message from a stream.
@@ -106,7 +105,7 @@ parse(SyncReadStream& stream,
@param stream The stream from which the data is to be read. @param stream The stream from which the data is to be read.
The type must support the @b `AsyncReadStream` concept. The type must support the @b `AsyncReadStream` concept.
@param streambuf A `Streambuf` holding additional bytes @param dynabuf A @b `DynamicBuffer` holding additional bytes
read by the implementation from the stream. This is both read by the implementation from the stream. This is both
an input and an output parameter; on entry, any data in the an input and an output parameter; on entry, any data in the
stream buffer's input sequence will be given to the parser stream buffer's input sequence will be given to the parser
@@ -128,14 +127,14 @@ parse(SyncReadStream& stream,
manner equivalent to using `boost::asio::io_service::post`. manner equivalent to using `boost::asio::io_service::post`.
*/ */
template<class AsyncReadStream, template<class AsyncReadStream,
class Streambuf, class Parser, class ReadHandler> class DynamicBuffer, class Parser, class ReadHandler>
#if GENERATING_DOCS #if GENERATING_DOCS
void_or_deduced void_or_deduced
#else #else
typename async_completion< typename async_completion<
ReadHandler, void(error_code)>::result_type ReadHandler, void(error_code)>::result_type
#endif #endif
async_parse(AsyncReadStream& stream, Streambuf& streambuf, async_parse(AsyncReadStream& stream, DynamicBuffer& dynabuf,
Parser& parser, ReadHandler&& handler); Parser& parser, ReadHandler&& handler);
/** Read a HTTP/1 message from a stream. /** Read a HTTP/1 message from a stream.
@@ -157,7 +156,7 @@ async_parse(AsyncReadStream& stream, Streambuf& streambuf,
@param stream The stream from which the data is to be read. @param stream The stream from which the data is to be read.
The type must support the @b `SyncReadStream` concept. The type must support the @b `SyncReadStream` concept.
@param streambuf A `Streambuf` holding additional bytes @param dynabuf A @b `DynamicBuffer` holding additional bytes
read by the implementation from the stream. This is both read by the implementation from the stream. This is both
an input and an output parameter; on entry, any data in the an input and an output parameter; on entry, any data in the
stream buffer's input sequence will be given to the parser stream buffer's input sequence will be given to the parser
@@ -168,10 +167,10 @@ async_parse(AsyncReadStream& stream, Streambuf& streambuf,
@throws boost::system::system_error Thrown on failure. @throws boost::system::system_error Thrown on failure.
*/ */
template<class SyncReadStream, class Streambuf, template<class SyncReadStream, class DynamicBuffer,
bool isRequest, class Body, class Headers> bool isRequest, class Body, class Headers>
void void
read(SyncReadStream& stream, Streambuf& streambuf, read(SyncReadStream& stream, DynamicBuffer& dynabuf,
message_v1<isRequest, Body, Headers>& msg); message_v1<isRequest, Body, Headers>& msg);
/** Read a HTTP/1 message from a stream. /** Read a HTTP/1 message from a stream.
@@ -193,7 +192,7 @@ read(SyncReadStream& stream, Streambuf& streambuf,
@param stream The stream from which the data is to be read. @param stream The stream from which the data is to be read.
The type must support the @b `SyncReadStream` concept. The type must support the @b `SyncReadStream` concept.
@param streambuf A `Streambuf` holding additional bytes @param dynabuf A @b `DynamicBuffer` holding additional bytes
read by the implementation from the stream. This is both read by the implementation from the stream. This is both
an input and an output parameter; on entry, any data in the an input and an output parameter; on entry, any data in the
stream buffer's input sequence will be given to the parser stream buffer's input sequence will be given to the parser
@@ -204,10 +203,10 @@ read(SyncReadStream& stream, Streambuf& streambuf,
@param ec Set to the error, if any occurred. @param ec Set to the error, if any occurred.
*/ */
template<class SyncReadStream, class Streambuf, template<class SyncReadStream, class DynamicBuffer,
bool isRequest, class Body, class Headers> bool isRequest, class Body, class Headers>
void void
read(SyncReadStream& stream, Streambuf& streambuf, read(SyncReadStream& stream, DynamicBuffer& dynabuf,
message_v1<isRequest, Body, Headers>& msg, message_v1<isRequest, Body, Headers>& msg,
error_code& ec); error_code& ec);
@@ -229,7 +228,7 @@ read(SyncReadStream& stream, Streambuf& streambuf,
@param stream The stream to read the message from. @param stream The stream to read the message from.
The type must support the @b `AsyncReadStream` concept. The type must support the @b `AsyncReadStream` concept.
@param streambuf A `Streambuf` holding additional bytes @param dynabuf A @b `DynamicBuffer` holding additional bytes
read by the implementation from the stream. This is both read by the implementation from the stream. This is both
an input and an output parameter; on entry, any data in the an input and an output parameter; on entry, any data in the
stream buffer's input sequence will be given to the parser stream buffer's input sequence will be given to the parser
@@ -249,7 +248,7 @@ read(SyncReadStream& stream, Streambuf& streambuf,
this function. Invocation of the handler will be performed in a this function. Invocation of the handler will be performed in a
manner equivalent to using `boost::asio::io_service::post`. manner equivalent to using `boost::asio::io_service::post`.
*/ */
template<class AsyncReadStream, class Streambuf, template<class AsyncReadStream, class DynamicBuffer,
bool isRequest, class Body, class Headers, bool isRequest, class Body, class Headers,
class ReadHandler> class ReadHandler>
#if GENERATING_DOCS #if GENERATING_DOCS
@@ -258,7 +257,7 @@ void_or_deduced
typename async_completion< typename async_completion<
ReadHandler, void(error_code)>::result_type ReadHandler, void(error_code)>::result_type
#endif #endif
async_read(AsyncReadStream& stream, Streambuf& streambuf, async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf,
message_v1<isRequest, Body, Headers>& msg, message_v1<isRequest, Body, Headers>& msg,
ReadHandler&& handler); ReadHandler&& handler);

View File

@@ -8,91 +8,17 @@
#ifndef BEAST_HTTP_STREAMBUF_BODY_HPP #ifndef BEAST_HTTP_STREAMBUF_BODY_HPP
#define BEAST_HTTP_STREAMBUF_BODY_HPP #define BEAST_HTTP_STREAMBUF_BODY_HPP
#include <beast/http/body_type.hpp> #include <beast/http/basic_dynabuf_body.hpp>
#include <beast/core/buffer_cat.hpp>
#include <beast/core/streambuf.hpp> #include <beast/core/streambuf.hpp>
#include <memory>
#include <string>
namespace beast { namespace beast {
namespace http { namespace http {
/** A message body represented by a Streambuf /** A message body represented by a @ref streambuf
Meets the requirements of @b `Body`. Meets the requirements of @b `Body`.
*/ */
template<class Streambuf> using streambuf_body = basic_dynabuf_body<streambuf>;
struct basic_streambuf_body
{
/// The type of the `message::body` member
using value_type = Streambuf;
#if GENERATING_DOCS
private:
#endif
class reader
{
value_type& sb_;
public:
template<bool isRequest, class Headers>
explicit
reader(message<isRequest,
basic_streambuf_body, Headers>& m) noexcept
: sb_(m.body)
{
}
void
write(void const* data,
std::size_t size, error_code&) noexcept
{
using boost::asio::buffer;
using boost::asio::buffer_copy;
sb_.commit(buffer_copy(
sb_.prepare(size), buffer(data, size)));
}
};
class writer
{
Streambuf const& body_;
public:
writer(writer const&) = delete;
writer& operator=(writer const&) = delete;
template<bool isRequest, class Headers>
explicit
writer(message<
isRequest, basic_streambuf_body, Headers> const& m)
: body_(m.body)
{
}
void
init(error_code& ec)
{
}
std::uint64_t
content_length() const
{
return body_.size();
}
template<class Write>
boost::tribool
operator()(resume_context&&, error_code&, Write&& write)
{
write(body_.data());
return true;
}
};
};
using streambuf_body = basic_streambuf_body<streambuf>;
} // http } // http
} // beast } // beast

View File

@@ -9,8 +9,7 @@
#define BEAST_HTTP_STRING_BODY_HPP #define BEAST_HTTP_STRING_BODY_HPP
#include <beast/http/body_type.hpp> #include <beast/http/body_type.hpp>
#include <beast/core/buffer_cat.hpp> #include <boost/asio/buffer.hpp>
#include <beast/core/streambuf.hpp>
#include <memory> #include <memory>
#include <string> #include <string>

View File

@@ -117,11 +117,11 @@ is_valid(close_code::value code)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Write frame header to streambuf // Write frame header to dynamic buffer
// //
template<class Streambuf> template<class DynamicBuffer>
void void
write(Streambuf& sb, frame_header const& fh) write(DynamicBuffer& db, frame_header const& fh)
{ {
using boost::asio::buffer; using boost::asio::buffer;
using boost::asio::buffer_copy; using boost::asio::buffer_copy;
@@ -159,24 +159,24 @@ write(Streambuf& sb, frame_header const& fh)
native_to_little_uint32(fh.key, &b[n]); native_to_little_uint32(fh.key, &b[n]);
n += 4; n += 4;
} }
sb.commit(buffer_copy( db.commit(buffer_copy(
sb.prepare(n), buffer(b))); db.prepare(n), buffer(b)));
} }
// Read fixed frame header // Read fixed frame header
// Requires at least 2 bytes // Requires at least 2 bytes
// //
template<class Streambuf> template<class DynamicBuffer>
std::size_t std::size_t
read_fh1(frame_header& fh, Streambuf& sb, read_fh1(frame_header& fh, DynamicBuffer& db,
role_type role, close_code::value& code) role_type role, close_code::value& code)
{ {
using boost::asio::buffer; using boost::asio::buffer;
using boost::asio::buffer_copy; using boost::asio::buffer_copy;
using boost::asio::buffer_size; using boost::asio::buffer_size;
std::uint8_t b[2]; std::uint8_t b[2];
assert(buffer_size(sb.data()) >= sizeof(b)); assert(buffer_size(db.data()) >= sizeof(b));
sb.consume(buffer_copy(buffer(b), sb.data())); db.consume(buffer_copy(buffer(b), db.data()));
std::size_t need; std::size_t need;
fh.len = b[1] & 0x7f; fh.len = b[1] & 0x7f;
switch(fh.len) switch(fh.len)
@@ -236,9 +236,9 @@ read_fh1(frame_header& fh, Streambuf& sb,
// Decode variable frame header from stream // Decode variable frame header from stream
// //
template<class Streambuf> template<class DynamicBuffer>
void void
read_fh2(frame_header& fh, Streambuf& sb, read_fh2(frame_header& fh, DynamicBuffer& db,
role_type role, close_code::value& code) role_type role, close_code::value& code)
{ {
using boost::asio::buffer; using boost::asio::buffer;
@@ -250,8 +250,8 @@ read_fh2(frame_header& fh, Streambuf& sb,
case 126: case 126:
{ {
std::uint8_t b[2]; std::uint8_t b[2];
assert(buffer_size(sb.data()) >= sizeof(b)); assert(buffer_size(db.data()) >= sizeof(b));
sb.consume(buffer_copy(buffer(b), sb.data())); db.consume(buffer_copy(buffer(b), db.data()));
fh.len = big_uint16_to_native(&b[0]); fh.len = big_uint16_to_native(&b[0]);
// length not canonical // length not canonical
if(fh.len < 126) if(fh.len < 126)
@@ -264,8 +264,8 @@ read_fh2(frame_header& fh, Streambuf& sb,
case 127: case 127:
{ {
std::uint8_t b[8]; std::uint8_t b[8];
assert(buffer_size(sb.data()) >= sizeof(b)); assert(buffer_size(db.data()) >= sizeof(b));
sb.consume(buffer_copy(buffer(b), sb.data())); db.consume(buffer_copy(buffer(b), db.data()));
fh.len = big_uint64_to_native(&b[0]); fh.len = big_uint64_to_native(&b[0]);
// length not canonical // length not canonical
if(fh.len < 65536) if(fh.len < 65536)
@@ -279,8 +279,8 @@ read_fh2(frame_header& fh, Streambuf& sb,
if(fh.mask) if(fh.mask)
{ {
std::uint8_t b[4]; std::uint8_t b[4];
assert(buffer_size(sb.data()) >= sizeof(b)); assert(buffer_size(db.data()) >= sizeof(b));
sb.consume(buffer_copy(buffer(b), sb.data())); db.consume(buffer_copy(buffer(b), db.data()));
fh.key = little_uint32_to_native(&b[0]); fh.key = little_uint32_to_native(&b[0]);
} }
else else

View File

@@ -18,7 +18,6 @@
#include <beast/http/empty_body.hpp> #include <beast/http/empty_body.hpp>
#include <beast/http/message.hpp> #include <beast/http/message.hpp>
#include <beast/http/string_body.hpp> #include <beast/http/string_body.hpp>
#include <beast/core/streambuf.hpp>
#include <boost/asio/error.hpp> #include <boost/asio/error.hpp>
#include <cassert> #include <cassert>
#include <cstdint> #include <cstdint>
@@ -107,15 +106,13 @@ protected:
void void
prepare_fh(close_code::value& code); prepare_fh(close_code::value& code);
template<class Streambuf> template<class DynamicBuffer>
void void
write_close(Streambuf& sb, write_close(DynamicBuffer& db, close_reason const& rc);
close_reason const& rc);
template<class Streambuf> template<class DynamicBuffer>
void void
write_ping(Streambuf& sb, opcode op, write_ping(DynamicBuffer& db, opcode op, ping_data const& data);
ping_data const& data);
}; };
} // detail } // detail

View File

@@ -23,7 +23,7 @@ namespace websocket {
// processes any received control frames. // processes any received control frames.
// //
template<class NextLayer> template<class NextLayer>
template<class Streambuf, class Handler> template<class DynamicBuffer, class Handler>
class stream<NextLayer>::read_frame_op class stream<NextLayer>::read_frame_op
{ {
using alloc_type = using alloc_type =
@@ -35,27 +35,27 @@ class stream<NextLayer>::read_frame_op
using fmb_type = using fmb_type =
typename fb_type::mutable_buffers_type; typename fb_type::mutable_buffers_type;
using smb_type = using dmb_type =
typename Streambuf::mutable_buffers_type; typename DynamicBuffer::mutable_buffers_type;
struct data : op struct data : op
{ {
stream<NextLayer>& ws; stream<NextLayer>& ws;
frame_info& fi; frame_info& fi;
Streambuf& sb; DynamicBuffer& db;
Handler h; Handler h;
fb_type fb; fb_type fb;
boost::optional<smb_type> smb; boost::optional<dmb_type> dmb;
boost::optional<fmb_type> fmb; boost::optional<fmb_type> fmb;
bool cont; bool cont;
int state = 0; int state = 0;
template<class DeducedHandler> template<class DeducedHandler>
data(DeducedHandler&& h_, stream<NextLayer>& ws_, data(DeducedHandler&& h_, stream<NextLayer>& ws_,
frame_info& fi_, Streambuf& sb_) frame_info& fi_, DynamicBuffer& sb_)
: ws(ws_) : ws(ws_)
, fi(fi_) , fi(fi_)
, sb(sb_) , db(sb_)
, h(std::forward<DeducedHandler>(h_)) , h(std::forward<DeducedHandler>(h_))
, cont(boost_asio_handler_cont_helpers:: , cont(boost_asio_handler_cont_helpers::
is_continuation(h)) is_continuation(h))
@@ -127,9 +127,9 @@ public:
}; };
template<class NextLayer> template<class NextLayer>
template<class Buffers, class Handler> template<class DynamicBuffer, class Handler>
void void
stream<NextLayer>::read_frame_op<Buffers, Handler>:: stream<NextLayer>::read_frame_op<DynamicBuffer, Handler>::
operator()(error_code ec, std::size_t bytes_transferred) operator()(error_code ec, std::size_t bytes_transferred)
{ {
auto& d = *d_; auto& d = *d_;
@@ -139,9 +139,9 @@ operator()(error_code ec, std::size_t bytes_transferred)
} }
template<class NextLayer> template<class NextLayer>
template<class Buffers, class Handler> template<class DynamicBuffer, class Handler>
void void
stream<NextLayer>::read_frame_op<Buffers, Handler>:: stream<NextLayer>::read_frame_op<DynamicBuffer, Handler>::
operator()(error_code ec,std::size_t bytes_transferred, bool again) operator()(error_code ec,std::size_t bytes_transferred, bool again)
{ {
enum enum
@@ -187,18 +187,18 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
case do_read_payload: case do_read_payload:
d.state = do_read_payload + 1; d.state = do_read_payload + 1;
d.smb = d.sb.prepare( d.dmb = d.db.prepare(
detail::clamp(d.ws.rd_need_)); detail::clamp(d.ws.rd_need_));
// receive payload data // receive payload data
d.ws.stream_.async_read_some( d.ws.stream_.async_read_some(
*d.smb, std::move(*this)); *d.dmb, std::move(*this));
return; return;
case do_read_payload + 1: case do_read_payload + 1:
{ {
d.ws.rd_need_ -= bytes_transferred; d.ws.rd_need_ -= bytes_transferred;
auto const pb = prepare_buffers( auto const pb = prepare_buffers(
bytes_transferred, *d.smb); bytes_transferred, *d.dmb);
if(d.ws.rd_fh_.mask) if(d.ws.rd_fh_.mask)
detail::mask_inplace(pb, d.ws.rd_key_); detail::mask_inplace(pb, d.ws.rd_key_);
if(d.ws.rd_opcode_ == opcode::text) if(d.ws.rd_opcode_ == opcode::text)
@@ -213,7 +213,7 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
break; break;
} }
} }
d.sb.commit(bytes_transferred); d.db.commit(bytes_transferred);
if(d.ws.rd_need_ > 0) if(d.ws.rd_need_ > 0)
{ {
d.state = do_read_payload; d.state = do_read_payload;

View File

@@ -17,7 +17,7 @@ namespace websocket {
// read an entire message // read an entire message
// //
template<class NextLayer> template<class NextLayer>
template<class Streambuf, class Handler> template<class DynamicBuffer, class Handler>
class stream<NextLayer>::read_op class stream<NextLayer>::read_op
{ {
using alloc_type = using alloc_type =
@@ -27,7 +27,7 @@ class stream<NextLayer>::read_op
{ {
stream<NextLayer>& ws; stream<NextLayer>& ws;
opcode& op; opcode& op;
Streambuf& sb; DynamicBuffer& db;
Handler h; Handler h;
frame_info fi; frame_info fi;
bool cont; bool cont;
@@ -36,10 +36,10 @@ class stream<NextLayer>::read_op
template<class DeducedHandler> template<class DeducedHandler>
data(DeducedHandler&& h_, data(DeducedHandler&& h_,
stream<NextLayer>& ws_, opcode& op_, stream<NextLayer>& ws_, opcode& op_,
Streambuf& sb_) DynamicBuffer& sb_)
: ws(ws_) : ws(ws_)
, op(op_) , op(op_)
, sb(sb_) , db(sb_)
, h(std::forward<DeducedHandler>(h_)) , h(std::forward<DeducedHandler>(h_))
, cont(boost_asio_handler_cont_helpers:: , cont(boost_asio_handler_cont_helpers::
is_continuation(h)) is_continuation(h))
@@ -98,9 +98,9 @@ public:
}; };
template<class NextLayer> template<class NextLayer>
template<class Streambuf, class Handler> template<class DynamicBuffer, class Handler>
void void
stream<NextLayer>::read_op<Streambuf, Handler>:: stream<NextLayer>::read_op<DynamicBuffer, Handler>::
operator()(error_code const& ec, bool again) operator()(error_code const& ec, bool again)
{ {
auto& d = *d_; auto& d = *d_;
@@ -117,9 +117,9 @@ operator()(error_code const& ec, bool again)
// the handler is moved from the data block // the handler is moved from the data block
// before asio_handler_deallocate is called. // before asio_handler_deallocate is called.
d.ws.async_read_frame( d.ws.async_read_frame(
d.fi, d.sb, std::move(*this)); d.fi, d.db, std::move(*this));
#else #else
d.ws.async_read_frame(d.fi, d.sb, *this); d.ws.async_read_frame(d.fi, d.db, *this);
#endif #endif
return; return;

View File

@@ -29,7 +29,6 @@
#include <beast/core/prepare_buffers.hpp> #include <beast/core/prepare_buffers.hpp>
#include <beast/core/static_streambuf.hpp> #include <beast/core/static_streambuf.hpp>
#include <beast/core/stream_concepts.hpp> #include <beast/core/stream_concepts.hpp>
#include <beast/core/streambuf.hpp>
#include <boost/endian/buffers.hpp> #include <boost/endian/buffers.hpp>
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
@@ -94,10 +93,10 @@ stream_base::prepare_fh(close_code::value& code)
} }
} }
template<class Streambuf> template<class DynamicBuffer>
void void
stream_base::write_close( stream_base::write_close(
Streambuf& sb, close_reason const& cr) DynamicBuffer& db, close_reason const& cr)
{ {
using namespace boost::endian; using namespace boost::endian;
frame_header fh; frame_header fh;
@@ -111,7 +110,7 @@ stream_base::write_close(
fh.mask = role_ == detail::role_type::client; fh.mask = role_ == detail::role_type::client;
if(fh.mask) if(fh.mask)
fh.key = maskgen_(); fh.key = maskgen_();
detail::write(sb, fh); detail::write(db, fh);
if(cr.code != close_code::none) if(cr.code != close_code::none)
{ {
detail::prepared_key_type key; detail::prepared_key_type key;
@@ -121,29 +120,29 @@ stream_base::write_close(
std::uint8_t b[2]; std::uint8_t b[2];
::new(&b[0]) big_uint16_buf_t{ ::new(&b[0]) big_uint16_buf_t{
(std::uint16_t)cr.code}; (std::uint16_t)cr.code};
auto d = sb.prepare(2); auto d = db.prepare(2);
boost::asio::buffer_copy(d, boost::asio::buffer_copy(d,
boost::asio::buffer(b)); boost::asio::buffer(b));
if(fh.mask) if(fh.mask)
detail::mask_inplace(d, key); detail::mask_inplace(d, key);
sb.commit(2); db.commit(2);
} }
if(! cr.reason.empty()) if(! cr.reason.empty())
{ {
auto d = sb.prepare(cr.reason.size()); auto d = db.prepare(cr.reason.size());
boost::asio::buffer_copy(d, boost::asio::buffer_copy(d,
boost::asio::const_buffer( boost::asio::const_buffer(
cr.reason.data(), cr.reason.size())); cr.reason.data(), cr.reason.size()));
if(fh.mask) if(fh.mask)
detail::mask_inplace(d, key); detail::mask_inplace(d, key);
sb.commit(cr.reason.size()); db.commit(cr.reason.size());
} }
} }
} }
template<class Streambuf> template<class DynamicBuffer>
void void
stream_base::write_ping(Streambuf& sb, stream_base::write_ping(DynamicBuffer& db,
opcode op, ping_data const& data) opcode op, ping_data const& data)
{ {
frame_header fh; frame_header fh;
@@ -156,19 +155,19 @@ stream_base::write_ping(Streambuf& sb,
fh.mask = role_ == role_type::client; fh.mask = role_ == role_type::client;
if(fh.mask) if(fh.mask)
fh.key = maskgen_(); fh.key = maskgen_();
detail::write(sb, fh); detail::write(db, fh);
if(data.empty()) if(data.empty())
return; return;
detail::prepared_key_type key; detail::prepared_key_type key;
if(fh.mask) if(fh.mask)
detail::prepare_key(key, fh.key); detail::prepare_key(key, fh.key);
auto d = sb.prepare(data.size()); auto d = db.prepare(data.size());
boost::asio::buffer_copy(d, boost::asio::buffer_copy(d,
boost::asio::const_buffers_1( boost::asio::const_buffers_1(
data.data(), data.size())); data.data(), data.size()));
if(fh.mask) if(fh.mask)
detail::mask_inplace(d, key); detail::mask_inplace(d, key);
sb.commit(data.size()); db.commit(data.size());
} }
} // detail } // detail
@@ -453,10 +452,10 @@ void
stream<NextLayer>:: stream<NextLayer>::
ping(ping_data const& payload, error_code& ec) ping(ping_data const& payload, error_code& ec)
{ {
detail::frame_streambuf sb; detail::frame_streambuf db;
write_ping<static_streambuf>( write_ping<static_streambuf>(
sb, opcode::ping, payload); db, opcode::ping, payload);
boost::asio::write(stream_, sb.data(), ec); boost::asio::write(stream_, db.data(), ec);
} }
template<class NextLayer> template<class NextLayer>
@@ -477,31 +476,35 @@ async_ping(ping_data const& payload, PingHandler&& handler)
} }
template<class NextLayer> template<class NextLayer>
template<class Streambuf> template<class DynamicBuffer>
void void
stream<NextLayer>:: stream<NextLayer>::
read(opcode& op, Streambuf& streambuf) read(opcode& op, DynamicBuffer& dynabuf)
{ {
static_assert(is_SyncStream<next_layer_type>::value, static_assert(is_SyncStream<next_layer_type>::value,
"SyncStream requirements not met"); "SyncStream requirements not met");
static_assert(beast::is_DynamicBuffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met");
error_code ec; error_code ec;
read(op, streambuf, ec); read(op, dynabuf, ec);
if(ec) if(ec)
throw system_error{ec}; throw system_error{ec};
} }
template<class NextLayer> template<class NextLayer>
template<class Streambuf> template<class DynamicBuffer>
void void
stream<NextLayer>:: stream<NextLayer>::
read(opcode& op, Streambuf& streambuf, error_code& ec) read(opcode& op, DynamicBuffer& dynabuf, error_code& ec)
{ {
static_assert(is_SyncStream<next_layer_type>::value, static_assert(is_SyncStream<next_layer_type>::value,
"SyncStream requirements not met"); "SyncStream requirements not met");
static_assert(beast::is_DynamicBuffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met");
frame_info fi; frame_info fi;
for(;;) for(;;)
{ {
read_frame(fi, streambuf, ec); read_frame(fi, dynabuf, ec);
if(ec) if(ec)
break; break;
op = fi.op; op = fi.op;
@@ -511,47 +514,51 @@ read(opcode& op, Streambuf& streambuf, error_code& ec)
} }
template<class NextLayer> template<class NextLayer>
template<class Streambuf, class ReadHandler> template<class DynamicBuffer, class ReadHandler>
typename async_completion< typename async_completion<
ReadHandler, void(error_code)>::result_type ReadHandler, void(error_code)>::result_type
stream<NextLayer>:: stream<NextLayer>::
async_read(opcode& op, async_read(opcode& op,
Streambuf& streambuf, ReadHandler&& handler) DynamicBuffer& dynabuf, ReadHandler&& handler)
{ {
static_assert(is_AsyncStream<next_layer_type>::value, static_assert(is_AsyncStream<next_layer_type>::value,
"AsyncStream requirements requirements not met"); "AsyncStream requirements requirements not met");
static_assert(beast::is_Streambuf<Streambuf>::value, static_assert(beast::is_DynamicBuffer<DynamicBuffer>::value,
"Streambuf requirements not met"); "DynamicBuffer requirements not met");
beast::async_completion< beast::async_completion<
ReadHandler, void(error_code) ReadHandler, void(error_code)
> completion(handler); > completion(handler);
read_op<Streambuf, decltype(completion.handler)>{ read_op<DynamicBuffer, decltype(completion.handler)>{
completion.handler, *this, op, streambuf}; completion.handler, *this, op, dynabuf};
return completion.result.get(); return completion.result.get();
} }
template<class NextLayer> template<class NextLayer>
template<class Streambuf> template<class DynamicBuffer>
void void
stream<NextLayer>:: stream<NextLayer>::
read_frame(frame_info& fi, Streambuf& streambuf) read_frame(frame_info& fi, DynamicBuffer& dynabuf)
{ {
static_assert(is_SyncStream<next_layer_type>::value, static_assert(is_SyncStream<next_layer_type>::value,
"SyncStream requirements not met"); "SyncStream requirements not met");
static_assert(beast::is_DynamicBuffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met");
error_code ec; error_code ec;
read_frame(fi, streambuf, ec); read_frame(fi, dynabuf, ec);
if(ec) if(ec)
throw system_error{ec}; throw system_error{ec};
} }
template<class NextLayer> template<class NextLayer>
template<class Streambuf> template<class DynamicBuffer>
void void
stream<NextLayer>:: stream<NextLayer>::
read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec) read_frame(frame_info& fi, DynamicBuffer& dynabuf, error_code& ec)
{ {
static_assert(is_SyncStream<next_layer_type>::value, static_assert(is_SyncStream<next_layer_type>::value,
"SyncStream requirements not met"); "SyncStream requirements not met");
static_assert(beast::is_DynamicBuffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met");
close_code::value code{}; close_code::value code{};
for(;;) for(;;)
{ {
@@ -630,7 +637,7 @@ read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec)
} }
} }
// read payload // read payload
auto smb = streambuf.prepare( auto smb = dynabuf.prepare(
detail::clamp(rd_need_)); detail::clamp(rd_need_));
auto const bytes_transferred = auto const bytes_transferred =
stream_.read_some(smb, ec); stream_.read_some(smb, ec);
@@ -652,7 +659,7 @@ read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec)
break; break;
} }
} }
streambuf.commit(bytes_transferred); dynabuf.commit(bytes_transferred);
fi.op = rd_opcode_; fi.op = rd_opcode_;
fi.fin = rd_fh_.fin && rd_need_ == 0; fi.fin = rd_fh_.fin && rd_need_ == 0;
return; return;
@@ -686,21 +693,21 @@ read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec)
} }
template<class NextLayer> template<class NextLayer>
template<class Streambuf, class ReadHandler> template<class DynamicBuffer, class ReadHandler>
typename async_completion< typename async_completion<
ReadHandler, void(error_code)>::result_type ReadHandler, void(error_code)>::result_type
stream<NextLayer>:: stream<NextLayer>::
async_read_frame(frame_info& fi, async_read_frame(frame_info& fi,
Streambuf& streambuf, ReadHandler&& handler) DynamicBuffer& dynabuf, ReadHandler&& handler)
{ {
static_assert(is_AsyncStream<next_layer_type>::value, static_assert(is_AsyncStream<next_layer_type>::value,
"AsyncStream requirements requirements not met"); "AsyncStream requirements requirements not met");
static_assert(beast::is_Streambuf<Streambuf>::value, static_assert(beast::is_DynamicBuffer<DynamicBuffer>::value,
"Streambuf requirements not met"); "DynamicBuffer requirements not met");
beast::async_completion< beast::async_completion<
ReadHandler, void(error_code)> completion(handler); ReadHandler, void(error_code)> completion(handler);
read_frame_op<Streambuf, decltype(completion.handler)>{ read_frame_op<DynamicBuffer, decltype(completion.handler)>{
completion.handler, *this, fi, streambuf}; completion.handler, *this, fi, dynabuf};
return completion.result.get(); return completion.result.get();
} }
@@ -712,6 +719,9 @@ write(ConstBufferSequence const& buffers)
{ {
static_assert(is_SyncStream<next_layer_type>::value, static_assert(is_SyncStream<next_layer_type>::value,
"SyncStream requirements not met"); "SyncStream requirements not met");
static_assert(beast::is_ConstBufferSequence<
ConstBufferSequence>::value,
"ConstBufferSequence requirements not met");
error_code ec; error_code ec;
write(buffers, ec); write(buffers, ec);
if(ec) if(ec)
@@ -774,6 +784,9 @@ write_frame(bool fin, ConstBufferSequence const& buffers)
{ {
static_assert(is_SyncStream<next_layer_type>::value, static_assert(is_SyncStream<next_layer_type>::value,
"SyncStream requirements not met"); "SyncStream requirements not met");
static_assert(beast::is_ConstBufferSequence<
ConstBufferSequence>::value,
"ConstBufferSequence requirements not met");
error_code ec; error_code ec;
write_frame(fin, buffers, ec); write_frame(fin, buffers, ec);
if(ec) if(ec)

View File

@@ -12,7 +12,7 @@
#include <beast/websocket/detail/stream_base.hpp> #include <beast/websocket/detail/stream_base.hpp>
#include <beast/http/message_v1.hpp> #include <beast/http/message_v1.hpp>
#include <beast/http/string_body.hpp> #include <beast/http/string_body.hpp>
#include <beast/core/streambuf_readstream.hpp> #include <beast/core/dynabuf_readstream.hpp>
#include <beast/core/async_completion.hpp> #include <beast/core/async_completion.hpp>
#include <beast/core/detail/get_lowest_layer.hpp> #include <beast/core/detail/get_lowest_layer.hpp>
#include <boost/asio.hpp> #include <boost/asio.hpp>
@@ -78,7 +78,7 @@ struct frame_info
@par Concepts @par Concepts
@b `AsyncStream`, @b `AsyncStream`,
@b `Decorator`, @b `Decorator`,
@b `Streambuf`, @b `DynamicBuffer`,
@b `SyncStream` @b `SyncStream`
*/ */
template<class NextLayer> template<class NextLayer>
@@ -86,7 +86,7 @@ class stream : public detail::stream_base
{ {
friend class stream_test; friend class stream_test;
streambuf_readstream<NextLayer, streambuf> stream_; dynabuf_readstream<NextLayer, streambuf> stream_;
public: public:
/// The type of the next layer. /// The type of the next layer.
@@ -567,7 +567,7 @@ public:
@throws boost::system::system_error Thrown on failure. @throws boost::system::system_error Thrown on failure.
*/ */
// VFALCO TODO This should also take a streambuf with any leftover bytes. // VFALCO TODO This should also take a DynamicBuffer with any leftover bytes.
template<class Body, class Headers> template<class Body, class Headers>
void void
accept(http::request_v1<Body, Headers> const& request); accept(http::request_v1<Body, Headers> const& request);
@@ -1007,14 +1007,14 @@ public:
@param op A value to receive the message type. @param op A value to receive the message type.
This object must remain valid until the handler is called. This object must remain valid until the handler is called.
@param streambuf A stream buffer to hold the message data. @param dynabuf A dynamic buffer to hold the message data after
This object must remain valid until the handler is called. any masking or decompression has been applied.
@throws boost::system::system_error Thrown on failure. @throws boost::system::system_error Thrown on failure.
*/ */
template<class Streambuf> template<class DynamicBuffer>
void void
read(opcode& op, Streambuf& streambuf); read(opcode& op, DynamicBuffer& dynabuf);
/** Read a message from the stream. /** Read a message from the stream.
@@ -1042,15 +1042,14 @@ public:
@param op A value to receive the message type. @param op A value to receive the message type.
This object must remain valid until the handler is called. This object must remain valid until the handler is called.
@param streambuf A stream buffer to hold the message data. @param dynabuf A dynamic buffer to hold the message data after
This object must remain valid until the handler is called. any masking or decompression has been applied.
@param ec Set to indicate what error occurred, if any. @param ec Set to indicate what error occurred, if any.
*/ */
template<class Streambuf> template<class DynamicBuffer>
void void
read(opcode& op, read(opcode& op, DynamicBuffer& dynabuf, error_code& ec);
Streambuf& streambuf, error_code& ec);
/** Start an asynchronous operation to read a message from the stream. /** Start an asynchronous operation to read a message from the stream.
@@ -1086,8 +1085,9 @@ public:
@param op A value to receive the message type. @param op A value to receive the message type.
This object must remain valid until the handler is called. This object must remain valid until the handler is called.
@param streambuf A stream buffer to hold the message data. @param dynabuf A dynamic buffer to hold the message data after
This object must remain valid until the handler is called. any masking or decompression has been applied. This object must
remain valid until the handler is called.
@param handler The handler to be called when the read operation @param handler The handler to be called when the read operation
completes. Copies will be made of the handler as required. The completes. Copies will be made of the handler as required. The
@@ -1102,15 +1102,14 @@ public:
this function. Invocation of the handler will be performed in a this function. Invocation of the handler will be performed in a
manner equivalent to using `boost::asio::io_service::post`. manner equivalent to using `boost::asio::io_service::post`.
*/ */
template<class Streambuf, class ReadHandler> template<class DynamicBuffer, class ReadHandler>
#if GENERATING_DOCS #if GENERATING_DOCS
void_or_deduced void_or_deduced
#else #else
typename async_completion< typename async_completion<
ReadHandler, void(error_code)>::result_type ReadHandler, void(error_code)>::result_type
#endif #endif
async_read(opcode& op, async_read(opcode& op, DynamicBuffer& dynabuf, ReadHandler&& handler);
Streambuf& streambuf, ReadHandler&& handler);
/** Read a message frame from the stream. /** Read a message frame from the stream.
@@ -1141,13 +1140,14 @@ public:
@param fi An object to store metadata about the message. @param fi An object to store metadata about the message.
@param streambuf A stream buffer to hold the message data. @param dynabuf A dynamic buffer to hold the message data after
any masking or decompression has been applied.
@throws boost::system::system_error Thrown on failure. @throws boost::system::system_error Thrown on failure.
*/ */
template<class Streambuf> template<class DynamicBuffer>
void void
read_frame(frame_info& fi, Streambuf& streambuf); read_frame(frame_info& fi, DynamicBuffer& dynabuf);
/** Read a message frame from the stream. /** Read a message frame from the stream.
@@ -1178,13 +1178,14 @@ public:
@param fi An object to store metadata about the message. @param fi An object to store metadata about the message.
@param streambuf A stream buffer to hold the message data. @param dynabuf A dynamic buffer to hold the message data after
any masking or decompression has been applied.
@param ec Set to indicate what error occurred, if any. @param ec Set to indicate what error occurred, if any.
*/ */
template<class Streambuf> template<class DynamicBuffer>
void void
read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec); read_frame(frame_info& fi, DynamicBuffer& dynabuf, error_code& ec);
/** Start an asynchronous operation to read a message frame from the stream. /** Start an asynchronous operation to read a message frame from the stream.
@@ -1225,7 +1226,7 @@ public:
@param fi An object to store metadata about the message. @param fi An object to store metadata about the message.
This object must remain valid until the handler is called. This object must remain valid until the handler is called.
@param streambuf A stream buffer to hold the message data after @param dynabuf A dynamic buffer to hold the message data after
any masking or decompression has been applied. This object must any masking or decompression has been applied. This object must
remain valid until the handler is called. remain valid until the handler is called.
@@ -1242,7 +1243,7 @@ public:
this function. Invocation of the handler will be performed in a this function. Invocation of the handler will be performed in a
manner equivalent to using boost::asio::io_service::post(). manner equivalent to using boost::asio::io_service::post().
*/ */
template<class Streambuf, class ReadHandler> template<class DynamicBuffer, class ReadHandler>
#if GENERATING_DOCS #if GENERATING_DOCS
void_or_deduced void_or_deduced
#else #else
@@ -1250,7 +1251,7 @@ public:
ReadHandler, void(error_code)>::result_type ReadHandler, void(error_code)>::result_type
#endif #endif
async_read_frame(frame_info& fi, async_read_frame(frame_info& fi,
Streambuf& streambuf, ReadHandler&& handler); DynamicBuffer& dynabuf, ReadHandler&& handler);
/** Write a message to the stream. /** Write a message to the stream.
@@ -1495,8 +1496,8 @@ private:
template<class Handler> class response_op; template<class Handler> class response_op;
template<class Buffers, class Handler> class write_op; template<class Buffers, class Handler> class write_op;
template<class Buffers, class Handler> class write_frame_op; template<class Buffers, class Handler> class write_frame_op;
template<class Streambuf, class Handler> class read_op; template<class DynamicBuffer, class Handler> class read_op;
template<class Streambuf, class Handler> class read_frame_op; template<class DynamicBuffer, class Handler> class read_frame_op;
void void
reset(); reset();

View File

@@ -21,6 +21,7 @@ unit-test core-tests :
core/buffer_concepts.cpp core/buffer_concepts.cpp
core/buffers_adapter.cpp core/buffers_adapter.cpp
core/consuming_buffers.cpp core/consuming_buffers.cpp
core/dynabuf_readstream.cpp
core/error.cpp core/error.cpp
core/handler_alloc.cpp core/handler_alloc.cpp
core/handler_concepts.cpp core/handler_concepts.cpp
@@ -30,9 +31,8 @@ unit-test core-tests :
core/static_string.cpp core/static_string.cpp
core/stream_concepts.cpp core/stream_concepts.cpp
core/streambuf.cpp core/streambuf.cpp
core/streambuf_readstream.cpp
core/to_string.cpp core/to_string.cpp
core/write_streambuf.cpp core/write_dynabuf.cpp
core/detail/base64.cpp core/detail/base64.cpp
core/detail/empty_base_optimization.cpp core/detail/empty_base_optimization.cpp
core/detail/get_lowest_layer.cpp core/detail/get_lowest_layer.cpp
@@ -41,6 +41,7 @@ unit-test core-tests :
unit-test http-tests : unit-test http-tests :
../extras/beast/unit_test/main.cpp ../extras/beast/unit_test/main.cpp
http/basic_dynabuf_body.cpp
http/basic_headers.cpp http/basic_headers.cpp
http/basic_parser_v1.cpp http/basic_parser_v1.cpp
http/body_type.cpp http/body_type.cpp

View File

@@ -15,6 +15,7 @@ add_executable (core-tests
buffer_concepts.cpp buffer_concepts.cpp
buffers_adapter.cpp buffers_adapter.cpp
consuming_buffers.cpp consuming_buffers.cpp
dynabuf_readstream.cpp
error.cpp error.cpp
handler_alloc.cpp handler_alloc.cpp
handler_concepts.cpp handler_concepts.cpp
@@ -24,9 +25,8 @@ add_executable (core-tests
static_string.cpp static_string.cpp
stream_concepts.cpp stream_concepts.cpp
streambuf.cpp streambuf.cpp
streambuf_readstream.cpp
to_string.cpp to_string.cpp
write_streambuf.cpp write_dynabuf.cpp
detail/base64.cpp detail/base64.cpp
detail/empty_base_optimization.cpp detail/empty_base_optimization.cpp
detail/get_lowest_layer.cpp detail/get_lowest_layer.cpp

View File

@@ -6,7 +6,7 @@
// //
// Test that header file is self-contained. // Test that header file is self-contained.
#include <beast/core/streambuf_readstream.hpp> #include <beast/core/dynabuf_readstream.hpp>
#include <beast/core/streambuf.hpp> #include <beast/core/streambuf.hpp>
#include <beast/test/fail_stream.hpp> #include <beast/test/fail_stream.hpp>
@@ -17,11 +17,11 @@
namespace beast { namespace beast {
class streambuf_readstream_test class dynabuf_readstream_test
: public unit_test::suite : public unit_test::suite
, public test::enable_yield_to , public test::enable_yield_to
{ {
using self = streambuf_readstream_test; using self = dynabuf_readstream_test;
public: public:
void testSpecialMembers() void testSpecialMembers()
@@ -29,16 +29,16 @@ public:
using socket_type = boost::asio::ip::tcp::socket; using socket_type = boost::asio::ip::tcp::socket;
boost::asio::io_service ios; boost::asio::io_service ios;
{ {
streambuf_readstream<socket_type, streambuf> srs(ios); dynabuf_readstream<socket_type, streambuf> srs(ios);
streambuf_readstream<socket_type, streambuf> srs2(std::move(srs)); dynabuf_readstream<socket_type, streambuf> srs2(std::move(srs));
srs = std::move(srs2); srs = std::move(srs2);
expect(&srs.get_io_service() == &ios); expect(&srs.get_io_service() == &ios);
expect(&srs.get_io_service() == &srs2.get_io_service()); expect(&srs.get_io_service() == &srs2.get_io_service());
} }
{ {
socket_type sock(ios); socket_type sock(ios);
streambuf_readstream<socket_type&, streambuf> srs(sock); dynabuf_readstream<socket_type&, streambuf> srs(sock);
streambuf_readstream<socket_type&, streambuf> srs2(std::move(srs)); dynabuf_readstream<socket_type&, streambuf> srs2(std::move(srs));
} }
} }
@@ -55,7 +55,7 @@ public:
{ {
test::fail_stream< test::fail_stream<
test::string_stream> fs(n, ios_, ", world!"); test::string_stream> fs(n, ios_, ", world!");
streambuf_readstream< dynabuf_readstream<
decltype(fs)&, streambuf> srs(fs); decltype(fs)&, streambuf> srs(fs);
srs.buffer().commit(buffer_copy( srs.buffer().commit(buffer_copy(
srs.buffer().prepare(5), buffer("Hello", 5))); srs.buffer().prepare(5), buffer("Hello", 5)));
@@ -73,7 +73,7 @@ public:
{ {
test::fail_stream< test::fail_stream<
test::string_stream> fs(n, ios_, ", world!"); test::string_stream> fs(n, ios_, ", world!");
streambuf_readstream< dynabuf_readstream<
decltype(fs)&, streambuf> srs(fs); decltype(fs)&, streambuf> srs(fs);
srs.capacity(3); srs.capacity(3);
srs.buffer().commit(buffer_copy( srs.buffer().commit(buffer_copy(
@@ -92,7 +92,7 @@ public:
{ {
test::fail_stream< test::fail_stream<
test::string_stream> fs(n, ios_, ", world!"); test::string_stream> fs(n, ios_, ", world!");
streambuf_readstream< dynabuf_readstream<
decltype(fs)&, streambuf> srs(fs); decltype(fs)&, streambuf> srs(fs);
srs.buffer().commit(buffer_copy( srs.buffer().commit(buffer_copy(
srs.buffer().prepare(5), buffer("Hello", 5))); srs.buffer().prepare(5), buffer("Hello", 5)));
@@ -111,7 +111,7 @@ public:
{ {
test::fail_stream< test::fail_stream<
test::string_stream> fs(n, ios_, ", world!"); test::string_stream> fs(n, ios_, ", world!");
streambuf_readstream< dynabuf_readstream<
decltype(fs)&, streambuf> srs(fs); decltype(fs)&, streambuf> srs(fs);
srs.capacity(3); srs.capacity(3);
srs.buffer().commit(buffer_copy( srs.buffer().commit(buffer_copy(
@@ -137,7 +137,7 @@ public:
} }
}; };
BEAST_DEFINE_TESTSUITE(streambuf_readstream,core,beast); BEAST_DEFINE_TESTSUITE(dynabuf_readstream,core,beast);
} // beast } // beast

View File

@@ -6,14 +6,14 @@
// //
// Test that header file is self-contained. // Test that header file is self-contained.
#include <beast/core/write_streambuf.hpp> #include <beast/core/write_dynabuf.hpp>
#include <beast/core/streambuf.hpp> #include <beast/core/streambuf.hpp>
#include <beast/unit_test/suite.hpp> #include <beast/unit_test/suite.hpp>
namespace beast { namespace beast {
class write_streambuf_test : public beast::unit_test::suite class write_dynabuf_test : public beast::unit_test::suite
{ {
public: public:
void run() override void run() override
@@ -31,6 +31,6 @@ public:
} }
}; };
BEAST_DEFINE_TESTSUITE(write_streambuf,core,beast); BEAST_DEFINE_TESTSUITE(write_dynabuf,core,beast);
} // beast } // beast

View File

@@ -7,6 +7,7 @@ GroupSources(test/http "/")
add_executable (http-tests add_executable (http-tests
${BEAST_INCLUDES} ${BEAST_INCLUDES}
../../extras/beast/unit_test/main.cpp ../../extras/beast/unit_test/main.cpp
basic_dynabuf_body.cpp
basic_headers.cpp basic_headers.cpp
basic_parser_v1.cpp basic_parser_v1.cpp
body_type.cpp body_type.cpp

View File

@@ -0,0 +1,9 @@
//
// Copyright (c) 2013-2016 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/http/basic_dynabuf_body.hpp>

View File

@@ -11,7 +11,7 @@
#include "message_fuzz.hpp" #include "message_fuzz.hpp"
#include <beast/core/streambuf.hpp> #include <beast/core/streambuf.hpp>
#include <beast/core/write_streambuf.hpp> #include <beast/core/write_dynabuf.hpp>
#include <beast/core/detail/ci_char_traits.hpp> #include <beast/core/detail/ci_char_traits.hpp>
#include <beast/http/rfc7230.hpp> #include <beast/http/rfc7230.hpp>
#include <beast/unit_test/suite.hpp> #include <beast/unit_test/suite.hpp>

View File

@@ -8,7 +8,7 @@
#ifndef BEAST_HTTP_TEST_MESSAGE_FUZZ_HPP #ifndef BEAST_HTTP_TEST_MESSAGE_FUZZ_HPP
#define BEAST_HTTP_TEST_MESSAGE_FUZZ_HPP #define BEAST_HTTP_TEST_MESSAGE_FUZZ_HPP
#include <beast/core/write_streambuf.hpp> #include <beast/core/write_dynabuf.hpp>
#include <beast/http/detail/basic_parser_v1.hpp> #include <beast/http/detail/basic_parser_v1.hpp>
#include <cstdint> #include <cstdint>
#include <random> #include <random>