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
* "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
* 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:
```C++
#include <beast/to_string.hpp>

View File

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

View File

@ -25,13 +25,13 @@ libraries:
* Let library users make the important decisions such as how to
allocate memory or how to leverage flow control.
Beast formalizes the [link beast.types.Streambuf [*`Streambuf`]] concept,
and relies heavily on the Boost.Asio [*`ConstBufferSequence`] and
[*`MutableBufferSequence`] concepts for passing buffers to functions.
The authors have found the `Streambuf` and buffer sequence interfaces
to be optimal for interacting with Asio, and for other tasks such as
incremental parsing of data in buffers (for example, parsing websocket
frames stored in a [link beast.ref.static_streambuf `static_streambuf`]).
Beast uses the [link beast.types.DynamicBuffer [*`DynamicBuffer`]] concept
presented in the Netwoking TS, and relies heavily on the Boost.Asio
[*`ConstBufferSequence`] and [*`MutableBufferSequence`] concepts for passing
buffers to functions. The authors have found the dynamic buffer and buffer
sequence interfaces to be optimal for interacting with Asio, and for other
tasks such as incremental parsing of data in buffers (for example, parsing
websocket frames stored in a [link beast.ref.static_streambuf `static_streambuf`]).
During the development of Beast the authors have studied other software
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";
```
* [link beast.ref.http__basic_streambuf_body [*`basic_streambuf_body`:]] A body with a
`value_type` of `streambuf`. A streambuf is an efficient storage object which
uses multiple octet arrays of varying lengths to represent data. Here is
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;
}
```
* [link beast.ref.http__streambuf_body [*`streambuf_body`:]] A body with a
`value_type` of [link beast.ref.streambuf `streambuf`]: an efficient storage
object which uses multiple octet arrays of varying lengths to represent data.
[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
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
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
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
[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);
...
@ -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
[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.
[endsect]

View File

@ -29,9 +29,9 @@
<entry valign="top">
<bridgehead renderas="sect3">Classes</bridgehead>
<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_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__headers">headers</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.buffers_adapter">buffers_adapter</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.handler_alloc">handler_alloc</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_string">static_string</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>
</simplelist>
</entry>
@ -164,8 +164,8 @@
<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_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_Streambuf">is_Streambuf</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_SyncWriteStream">is_SyncWriteStream</link></member>
@ -174,10 +174,10 @@
<entry valign="top">
<bridgehead renderas="sect3">Concepts</bridgehead>
<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.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.Streambuf">Streambuf</link></member>
<member><link linkend="beast.types.streams.SyncStream">SyncStream</link></member>
</simplelist>
</entry>

View File

@ -1552,15 +1552,15 @@
<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: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: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 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: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:text>class ``[link beast.types.streams.SyncStream [*SyncStream]]``</xsl:text>
</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
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`].
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/stream_concepts.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/write_streambuf.hpp>
#include <beast/core/write_dynabuf.hpp>
#endif

View File

@ -18,14 +18,14 @@
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
of varying sizes. Additional character array objects are appended to
the sequence to accommodate changes in the size of the character
sequence.
@note Meets the requirements of @b Streambuf.
@note Meets the requirements of @b `DynamicBuffer`.
@tparam Allocator The allocator to use for managing memory.
*/
@ -202,26 +202,37 @@ public:
basic_streambuf(std::size_t alloc_size = 1024,
Allocator const& alloc = allocator_type{});
/// Get the associated allocator
/// Returns a copy of the associated allocator.
allocator_type
get_allocator() const
{
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
max_size() const
{
return std::numeric_limits<std::size_t>::max();
}
/// Get the size of the input sequence.
size_type
size() const
{
return in_size_;
}
/// Returns the maximum sum of the sizes of the input sequence and output sequence the buffer can hold without requiring reallocation.
std::size_t
capacity() const;
/** 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.
@ -239,22 +250,11 @@ public:
void
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.
void
consume(size_type n);
/// Clear everything.
void
clear();
// Helper for read_until
// Helper for boost::asio::read_until
template<class OtherAllocator>
friend
std::size_t
@ -262,6 +262,9 @@ public:
OtherAllocator> const& streambuf, std::size_t max_size);
private:
void
clear();
void
move_assign(basic_streambuf& other, std::false_type);
@ -277,20 +280,17 @@ private:
void
delete_list();
std::size_t
prepare_size() const;
void
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.
@return The stream buffer.
@return A reference to the @ref basic_streambuf.
*/
template<class Allocator, class T>
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`.
template<class T>
#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
#endif

View File

@ -86,7 +86,7 @@ public:
};
template<class T>
class is_Streambuf
class is_DynamicBuffer
{
template<class U, class R = std::integral_constant<
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)
//
#ifndef BEAST_DETAIL_WRITE_STREAMBUF_HPP
#define BEAST_DETAIL_WRITE_STREAMBUF_HPP
#ifndef BEAST_DETAIL_WRITE_DYNABUF_HPP
#define BEAST_DETAIL_WRITE_DYNABUF_HPP
#include <beast/core/buffer_concepts.hpp>
#include <boost/asio/buffer.hpp>
@ -42,73 +42,73 @@ public:
! is_string_literal<T>::value;
};
template<class Streambuf>
template<class DynamicBuffer>
void
write_streambuf(Streambuf& streambuf,
write_dynabuf(DynamicBuffer& dynabuf,
boost::asio::const_buffer const& buffer)
{
using boost::asio::buffer_copy;
using boost::asio::buffer_size;
streambuf.commit(buffer_copy(
streambuf.prepare(buffer_size(buffer)),
dynabuf.commit(buffer_copy(
dynabuf.prepare(buffer_size(buffer)),
buffer));
}
template<class Streambuf>
template<class DynamicBuffer>
void
write_streambuf(Streambuf& streambuf,
write_dynabuf(DynamicBuffer& dynabuf,
boost::asio::mutable_buffer const& buffer)
{
using boost::asio::buffer_copy;
using boost::asio::buffer_size;
streambuf.commit(buffer_copy(
streambuf.prepare(buffer_size(buffer)),
dynabuf.commit(buffer_copy(
dynabuf.prepare(buffer_size(buffer)),
buffer));
}
template<class Streambuf, class T>
template<class DynamicBuffer, class T>
typename std::enable_if<
is_BufferConvertible<T>::value &&
! std::is_convertible<T, boost::asio::const_buffer>::value &&
! std::is_convertible<T, boost::asio::mutable_buffer>::value
>::type
write_streambuf(Streambuf& streambuf, T const& t)
write_dynabuf(DynamicBuffer& dynabuf, T const& t)
{
using boost::asio::buffer_copy;
using boost::asio::buffer_size;
auto const buffers = boost::asio::buffer(t);
streambuf.commit(buffer_copy(
streambuf.prepare(buffer_size(buffers)),
dynabuf.commit(buffer_copy(
dynabuf.prepare(buffer_size(buffers)),
buffers));
}
template<class Streambuf, class Buffers>
template<class DynamicBuffer, class Buffers>
typename std::enable_if<
is_ConstBufferSequence<Buffers>::value &&
! is_BufferConvertible<Buffers>::value &&
! std::is_convertible<Buffers, boost::asio::const_buffer>::value &&
! std::is_convertible<Buffers, boost::asio::mutable_buffer>::value
>::type
write_streambuf(Streambuf& streambuf, Buffers const& buffers)
write_dynabuf(DynamicBuffer& dynabuf, Buffers const& buffers)
{
using boost::asio::buffer_copy;
using boost::asio::buffer_size;
streambuf.commit(buffer_copy(
streambuf.prepare(buffer_size(buffers)),
dynabuf.commit(buffer_copy(
dynabuf.prepare(buffer_size(buffers)),
buffers));
}
template<class Streambuf, std::size_t N>
template<class DynamicBuffer, std::size_t N>
void
write_streambuf(Streambuf& streambuf, const char (&s)[N])
write_dynabuf(DynamicBuffer& dynabuf, const char (&s)[N])
{
using boost::asio::buffer_copy;
streambuf.commit(buffer_copy(
streambuf.prepare(N - 1),
dynabuf.commit(buffer_copy(
dynabuf.prepare(N - 1),
boost::asio::buffer(s, N - 1)));
}
template<class Streambuf, class T>
template<class DynamicBuffer, class T>
typename std::enable_if<
! is_string_literal<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::mutable_buffer>::value
>::type
write_streambuf(Streambuf& streambuf, T const& t)
write_dynabuf(DynamicBuffer& dynabuf, T const& t)
{
using boost::asio::buffer;
using boost::asio::buffer_copy;
auto const s = boost::lexical_cast<std::string>(t);
streambuf.commit(buffer_copy(
streambuf.prepare(s.size()), buffer(s)));
dynabuf.commit(buffer_copy(
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
write_streambuf(Streambuf& streambuf,
write_dynabuf(DynamicBuffer& dynabuf,
T0 const& t0, T1 const& t1, TN const&... tn)
{
write_streambuf(streambuf, t0);
write_streambuf(streambuf, t1, tn...);
write_dynabuf(dynabuf, t0);
write_dynabuf(dynabuf, t1, tn...);
}
} // detail

View File

@ -5,8 +5,8 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_STREAMBUF_READSTREAM_HPP
#define BEAST_STREAMBUF_READSTREAM_HPP
#ifndef BEAST_DYNABUF_READSTREAM_HPP
#define BEAST_DYNABUF_READSTREAM_HPP
#include <beast/core/async_completion.hpp>
#include <beast/core/buffer_concepts.hpp>
@ -22,11 +22,11 @@
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
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.
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,
// leaving excess bytes behind for the next call.
//
template<class Streambuf>
template<class DynamicBuffer>
void process_http_message(
streambuf_readstream<Streambuf>& stream)
dynabuf_readstream<DynamicBuffer>& stream)
{
// Read up to and including the end of the HTTP
// headers, leaving the sequence in the stream's
@ -85,24 +85,24 @@ namespace beast {
@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>
class streambuf_readstream
template<class Stream, class DynamicBuffer>
class dynabuf_readstream
{
static_assert(is_Streambuf<Streambuf>::value,
"Streambuf requirements not met");
static_assert(is_DynamicBuffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met");
template<class Buffers, class Handler>
class read_some_op;
Streambuf sb_;
DynamicBuffer sb_;
std::size_t capacity_ = 0;
Stream next_layer_;
public:
/// The type of the internal buffer
using streambuf_type = Streambuf;
using dynabuf_type = DynamicBuffer;
/// The type of the next layer.
using next_layer_type =
@ -122,14 +122,14 @@ public:
@note The behavior of move assignment on or from streams
with active or pending operations is undefined.
*/
streambuf_readstream(streambuf_readstream&&) = default;
dynabuf_readstream(dynabuf_readstream&&) = default;
/** Move assignment.
@note The behavior of move assignment on or from streams
with active or pending operations is undefined.
*/
streambuf_readstream& operator=(streambuf_readstream&&) = default;
dynabuf_readstream& operator=(dynabuf_readstream&&) = default;
/** Construct the wrapping stream.
@ -137,7 +137,7 @@ public:
*/
template<class... Args>
explicit
streambuf_readstream(Args&&... args);
dynabuf_readstream(Args&&... args);
/// Get a reference to the next layer.
next_layer_type&
@ -174,7 +174,7 @@ public:
by causing the internal buffer size to increase beyond
the caller defined maximum.
*/
Streambuf&
DynamicBuffer&
buffer()
{
return sb_;
@ -187,7 +187,7 @@ public:
by causing the internal buffer size to increase beyond
the caller defined maximum.
*/
Streambuf const&
DynamicBuffer const&
buffer() const
{
return sb_;
@ -275,6 +275,6 @@ public:
} // beast
#include <beast/core/impl/streambuf_readstream.ipp>
#include <beast/core/impl/dynabuf_readstream.ipp>
#endif

View File

@ -8,7 +8,7 @@
#ifndef 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 <cassert>
#include <exception>
@ -527,6 +527,28 @@ basic_streambuf<Allocator>::basic_streambuf(
"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>
auto
basic_streambuf<Allocator>::prepare(size_type n) ->
@ -646,14 +668,6 @@ basic_streambuf<Allocator>::commit(size_type n)
debug_check();
}
template<class Allocator>
auto
basic_streambuf<Allocator>::data() const ->
const_buffers_type
{
return const_buffers_type(*this);
}
template<class Allocator>
void
basic_streambuf<Allocator>::consume(size_type n)
@ -717,7 +731,8 @@ basic_streambuf<Allocator>::consume(size_type n)
template<class Allocator>
void
basic_streambuf<Allocator>::clear()
basic_streambuf<Allocator>::
clear()
{
delete_list();
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>
void
basic_streambuf<Allocator>::debug_check() const
@ -855,7 +855,7 @@ std::size_t
read_size_helper(basic_streambuf<
Allocator> const& streambuf, std::size_t max_size)
{
auto const avail = streambuf.prepare_size();
auto const avail = streambuf.capacity() - streambuf.size();
if(avail == 0)
return std::min(max_size,
std::max<std::size_t>(512, streambuf.alloc_size_));
@ -866,7 +866,7 @@ template<class Alloc, class T>
basic_streambuf<Alloc>&
operator<<(basic_streambuf<Alloc>& streambuf, T const& t)
{
detail::write_streambuf(streambuf, t);
detail::write_dynabuf(streambuf, t);
return streambuf;
}

View File

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

View File

@ -15,7 +15,7 @@
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.

View File

@ -5,20 +5,20 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_WRITE_STREAMBUF_HPP
#define BEAST_WRITE_STREAMBUF_HPP
#ifndef BEAST_WRITE_DYNABUF_HPP
#define BEAST_WRITE_DYNABUF_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 <utility>
namespace beast {
/** Write to a Streambuf.
/** Write to a @b `DynamicBuffer`.
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:
@li `boost::asio::const_buffer`
@ -33,29 +33,29 @@ namespace beast {
For all types not listed above, the function will invoke
`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
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.
@throws unspecified Any exceptions thrown by `boost::lexical_cast`.
@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
void
#else
typename std::enable_if<is_Streambuf<Streambuf>::value>::type
typename std::enable_if<is_DynamicBuffer<DynamicBuffer>::value>::type
#endif
write(Streambuf& streambuf, Args const&... args)
write(DynamicBuffer& dynabuf, Args const&... args)
{
detail::write_streambuf(streambuf, args...);
detail::write_dynabuf(dynabuf, args...);
}
} // 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
#include <beast/http/body_type.hpp>
#include <beast/core/streambuf.hpp>
#include <boost/asio/buffer.hpp>
#include <memory>
#include <string>

View File

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

View File

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

View File

@ -12,7 +12,6 @@
#include <beast/core/error.hpp>
#include <beast/core/async_completion.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/system/error_code.hpp>
namespace beast {
namespace http {
@ -36,7 +35,7 @@ namespace http {
@param stream The stream from which the data is to be read.
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
an input and an output parameter; on entry, any data in the
stream buffer's input sequence will be given to the parser
@ -47,10 +46,10 @@ namespace http {
@throws boost::system::system_error on failure.
*/
template<class SyncReadStream, class Streambuf, class Parser>
template<class SyncReadStream, class DynamicBuffer, class Parser>
void
parse(SyncReadStream& stream,
Streambuf& streambuf, Parser& parser);
DynamicBuffer& dynabuf, Parser& parser);
/** 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.
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
an input and an output parameter; on entry, any data in the
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.
*/
template<class SyncReadStream, class Streambuf, class Parser>
template<class SyncReadStream, class DynamicBuffer, class Parser>
void
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.
@ -106,7 +105,7 @@ parse(SyncReadStream& stream,
@param stream The stream from which the data is to be read.
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
an input and an output parameter; on entry, any data in the
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`.
*/
template<class AsyncReadStream,
class Streambuf, class Parser, class ReadHandler>
class DynamicBuffer, class Parser, class ReadHandler>
#if GENERATING_DOCS
void_or_deduced
#else
typename async_completion<
ReadHandler, void(error_code)>::result_type
#endif
async_parse(AsyncReadStream& stream, Streambuf& streambuf,
async_parse(AsyncReadStream& stream, DynamicBuffer& dynabuf,
Parser& parser, ReadHandler&& handler);
/** 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.
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
an input and an output parameter; on entry, any data in the
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.
*/
template<class SyncReadStream, class Streambuf,
template<class SyncReadStream, class DynamicBuffer,
bool isRequest, class Body, class Headers>
void
read(SyncReadStream& stream, Streambuf& streambuf,
read(SyncReadStream& stream, DynamicBuffer& dynabuf,
message_v1<isRequest, Body, Headers>& msg);
/** 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.
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
an input and an output parameter; on entry, any data in the
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.
*/
template<class SyncReadStream, class Streambuf,
template<class SyncReadStream, class DynamicBuffer,
bool isRequest, class Body, class Headers>
void
read(SyncReadStream& stream, Streambuf& streambuf,
read(SyncReadStream& stream, DynamicBuffer& dynabuf,
message_v1<isRequest, Body, Headers>& msg,
error_code& ec);
@ -229,7 +228,7 @@ read(SyncReadStream& stream, Streambuf& streambuf,
@param stream The stream to read the message from.
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
an input and an output parameter; on entry, any data in the
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
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,
class ReadHandler>
#if GENERATING_DOCS
@ -258,7 +257,7 @@ void_or_deduced
typename async_completion<
ReadHandler, void(error_code)>::result_type
#endif
async_read(AsyncReadStream& stream, Streambuf& streambuf,
async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf,
message_v1<isRequest, Body, Headers>& msg,
ReadHandler&& handler);

View File

@ -8,91 +8,17 @@
#ifndef BEAST_HTTP_STREAMBUF_BODY_HPP
#define BEAST_HTTP_STREAMBUF_BODY_HPP
#include <beast/http/body_type.hpp>
#include <beast/core/buffer_cat.hpp>
#include <beast/http/basic_dynabuf_body.hpp>
#include <beast/core/streambuf.hpp>
#include <memory>
#include <string>
namespace beast {
namespace http {
/** A message body represented by a Streambuf
/** A message body represented by a @ref streambuf
Meets the requirements of @b `Body`.
*/
template<class 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>;
using streambuf_body = basic_dynabuf_body<streambuf>;
} // http
} // beast

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -12,7 +12,7 @@
#include <beast/websocket/detail/stream_base.hpp>
#include <beast/http/message_v1.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/detail/get_lowest_layer.hpp>
#include <boost/asio.hpp>
@ -78,7 +78,7 @@ struct frame_info
@par Concepts
@b `AsyncStream`,
@b `Decorator`,
@b `Streambuf`,
@b `DynamicBuffer`,
@b `SyncStream`
*/
template<class NextLayer>
@ -86,7 +86,7 @@ class stream : public detail::stream_base
{
friend class stream_test;
streambuf_readstream<NextLayer, streambuf> stream_;
dynabuf_readstream<NextLayer, streambuf> stream_;
public:
/// The type of the next layer.
@ -567,7 +567,7 @@ public:
@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>
void
accept(http::request_v1<Body, Headers> const& request);
@ -1007,14 +1007,14 @@ public:
@param op A value to receive the message type.
This object must remain valid until the handler is called.
@param streambuf A stream buffer to hold the message data.
This object must remain valid until the handler is called.
@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.
*/
template<class Streambuf>
template<class DynamicBuffer>
void
read(opcode& op, Streambuf& streambuf);
read(opcode& op, DynamicBuffer& dynabuf);
/** Read a message from the stream.
@ -1042,15 +1042,14 @@ public:
@param op A value to receive the message type.
This object must remain valid until the handler is called.
@param streambuf A stream buffer to hold the message data.
This object must remain valid until the handler is called.
@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.
*/
template<class Streambuf>
template<class DynamicBuffer>
void
read(opcode& op,
Streambuf& streambuf, error_code& ec);
read(opcode& op, DynamicBuffer& dynabuf, error_code& ec);
/** 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.
This object must remain valid until the handler is called.
@param streambuf A stream buffer to hold the message data.
This object must remain valid until the handler is called.
@param dynabuf A dynamic buffer to hold the message data after
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
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
manner equivalent to using `boost::asio::io_service::post`.
*/
template<class Streambuf, class ReadHandler>
template<class DynamicBuffer, class ReadHandler>
#if GENERATING_DOCS
void_or_deduced
#else
typename async_completion<
ReadHandler, void(error_code)>::result_type
#endif
async_read(opcode& op,
Streambuf& streambuf, ReadHandler&& handler);
async_read(opcode& op, DynamicBuffer& dynabuf, ReadHandler&& handler);
/** Read a message frame from the stream.
@ -1141,13 +1140,14 @@ public:
@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.
*/
template<class Streambuf>
template<class DynamicBuffer>
void
read_frame(frame_info& fi, Streambuf& streambuf);
read_frame(frame_info& fi, DynamicBuffer& dynabuf);
/** Read a message frame from the stream.
@ -1178,13 +1178,14 @@ public:
@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.
*/
template<class Streambuf>
template<class DynamicBuffer>
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.
@ -1225,7 +1226,7 @@ public:
@param fi An object to store metadata about the message.
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
remain valid until the handler is called.
@ -1242,7 +1243,7 @@ public:
this function. Invocation of the handler will be performed in a
manner equivalent to using boost::asio::io_service::post().
*/
template<class Streambuf, class ReadHandler>
template<class DynamicBuffer, class ReadHandler>
#if GENERATING_DOCS
void_or_deduced
#else
@ -1250,7 +1251,7 @@ public:
ReadHandler, void(error_code)>::result_type
#endif
async_read_frame(frame_info& fi,
Streambuf& streambuf, ReadHandler&& handler);
DynamicBuffer& dynabuf, ReadHandler&& handler);
/** Write a message to the stream.
@ -1495,8 +1496,8 @@ private:
template<class Handler> class response_op;
template<class Buffers, class Handler> class write_op;
template<class Buffers, class Handler> class write_frame_op;
template<class Streambuf, class Handler> class read_op;
template<class Streambuf, class Handler> class read_frame_op;
template<class DynamicBuffer, class Handler> class read_op;
template<class DynamicBuffer, class Handler> class read_frame_op;
void
reset();

View File

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

View File

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

View File

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

View File

@ -6,14 +6,14 @@
//
// 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/unit_test/suite.hpp>
namespace beast {
class write_streambuf_test : public beast::unit_test::suite
class write_dynabuf_test : public beast::unit_test::suite
{
public:
void run() override
@ -31,6 +31,6 @@ public:
}
};
BEAST_DEFINE_TESTSUITE(write_streambuf,core,beast);
BEAST_DEFINE_TESTSUITE(write_dynabuf,core,beast);
} // beast

View File

@ -7,6 +7,7 @@ GroupSources(test/http "/")
add_executable (http-tests
${BEAST_INCLUDES}
../../extras/beast/unit_test/main.cpp
basic_dynabuf_body.cpp
basic_headers.cpp
basic_parser_v1.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 <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/http/rfc7230.hpp>
#include <beast/unit_test/suite.hpp>

View File

@ -8,7 +8,7 @@
#ifndef 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 <cstdint>
#include <random>