diff --git a/CHANGELOG b/CHANGELOG index 48e29388..ffce41c6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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 + -------------------------------------------------------------------------------- diff --git a/README.md b/README.md index a9c8a923..af2f595a 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/doc/beast.qbk b/doc/beast.qbk index 1b8cd352..f9d8b89a 100644 --- a/doc/beast.qbk +++ b/doc/beast.qbk @@ -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] diff --git a/doc/design.qbk b/doc/design.qbk index 5e90dac8..ff109d76 100644 --- a/doc/design.qbk +++ b/doc/design.qbk @@ -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 diff --git a/doc/http.qbk b/doc/http.qbk index f1b533d9..6089102a 100644 --- a/doc/http.qbk +++ b/doc/http.qbk @@ -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 - http::response> - make_response(ConstBufferSequence const& buffers) - { - http::response> 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] diff --git a/doc/quickref.xml b/doc/quickref.xml index 929876ff..3368eedc 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -29,9 +29,9 @@ Classes + basic_dynabuf_body basic_headers basic_parser_v1 - basic_streambuf_body empty_body headers message @@ -130,6 +130,7 @@ basic_streambuf buffers_adapter consuming_buffers + dynabuf_readstream error_code handler_alloc prepared_buffers @@ -137,7 +138,6 @@ static_streambuf_n static_string streambuf - streambuf_readstream system_error @@ -164,8 +164,8 @@ is_BufferSequence is_CompletionHandler is_ConstBufferSequence + is_DynamicBuffer is_MutableBufferSequence - is_Streambuf is_SyncReadStream is_SyncStream is_SyncWriteStream @@ -174,10 +174,10 @@ Concepts - BufferSequence AsyncStream + BufferSequence + DynamicBuffer Stream - Streambuf SyncStream diff --git a/doc/reference.xsl b/doc/reference.xsl index 0824f077..3a82f1e5 100644 --- a/doc/reference.xsl +++ b/doc/reference.xsl @@ -1552,15 +1552,15 @@ class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*ConstBufferSequence]]`` + + class ``[link beast.types.DynamicBuffer [*DynamicBuffer]]`` + class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/MutableBufferSequence.html [*MutableBufferSequence]]`` - + class ``[link beast.types.streams.Stream [*Stream]]`` - - class ``[link beast.types.Streambuf [*Streambuf]]`` - class ``[link beast.types.streams.SyncStream [*SyncStream]]`` diff --git a/doc/types/DynamicBuffer.qbk b/doc/types/DynamicBuffer.qbk new file mode 100644 index 00000000..dd0243bf --- /dev/null +++ b/doc/types/DynamicBuffer.qbk @@ -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] diff --git a/doc/types/Streambuf.qbk b/doc/types/Streambuf.qbk deleted file mode 100644 index 60bf88ed..00000000 --- a/doc/types/Streambuf.qbk +++ /dev/null @@ -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] diff --git a/doc/websocket.qbk b/doc/websocket.qbk index 617deb2a..da2808cc 100644 --- a/doc/websocket.qbk +++ b/doc/websocket.qbk @@ -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 diff --git a/include/beast/core.hpp b/include/beast/core.hpp index 26eb9cd7..dc750eea 100644 --- a/include/beast/core.hpp +++ b/include/beast/core.hpp @@ -24,8 +24,8 @@ #include #include #include -#include +#include #include -#include +#include #endif diff --git a/include/beast/core/basic_streambuf.hpp b/include/beast/core/basic_streambuf.hpp index b48a6d0f..6aee9603 100644 --- a/include/beast/core/basic_streambuf.hpp +++ b/include/beast/core/basic_streambuf.hpp @@ -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::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 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 basic_streambuf& diff --git a/include/beast/core/buffer_concepts.hpp b/include/beast/core/buffer_concepts.hpp index f99d716b..addc3cdf 100644 --- a/include/beast/core/buffer_concepts.hpp +++ b/include/beast/core/buffer_concepts.hpp @@ -35,6 +35,16 @@ struct is_ConstBufferSequence : { }; +/// Determine if `T` meets the requirements of @b `DynamicBuffer`. +template +#if GENERATING_DOCS +struct is_DynamicBuffer : std::integral_constant +#else +struct is_DynamicBuffer : detail::is_DynamicBuffer::type +#endif +{ +}; + /// Determine if `T` meets the requirements of @b `MutableBufferSequence`. template #if GENERATING_DOCS @@ -46,16 +56,6 @@ struct is_MutableBufferSequence : { }; -/// Determine if `T` meets the requirements of @b `Streambuf`. -template -#if GENERATING_DOCS -struct is_Streambuf : std::integral_constant -#else -struct is_Streambuf : detail::is_Streambuf::type -#endif -{ -}; - } // beast #endif diff --git a/include/beast/core/detail/buffer_concepts.hpp b/include/beast/core/detail/buffer_concepts.hpp index ce1451fb..2361e678 100644 --- a/include/beast/core/detail/buffer_concepts.hpp +++ b/include/beast/core/detail/buffer_concepts.hpp @@ -86,7 +86,7 @@ public: }; template -class is_Streambuf +class is_DynamicBuffer { template #include @@ -42,73 +42,73 @@ public: ! is_string_literal::value; }; -template +template 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 +template 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 +template typename std::enable_if< is_BufferConvertible::value && ! std::is_convertible::value && ! std::is_convertible::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 +template typename std::enable_if< is_ConstBufferSequence::value && ! is_BufferConvertible::value && ! std::is_convertible::value && ! std::is_convertible::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 +template 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 +template typename std::enable_if< ! is_string_literal::value && ! is_ConstBufferSequence::value && @@ -116,22 +116,22 @@ typename std::enable_if< ! std::is_convertible::value && ! std::is_convertible::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(t); - streambuf.commit(buffer_copy( - streambuf.prepare(s.size()), buffer(s))); + dynabuf.commit(buffer_copy( + dynabuf.prepare(s.size()), buffer(s))); } -template +template 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 diff --git a/include/beast/core/streambuf_readstream.hpp b/include/beast/core/dynabuf_readstream.hpp similarity index 90% rename from include/beast/core/streambuf_readstream.hpp rename to include/beast/core/dynabuf_readstream.hpp index e014f6d2..9e8199db 100644 --- a/include/beast/core/streambuf_readstream.hpp +++ b/include/beast/core/dynabuf_readstream.hpp @@ -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 #include @@ -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 + template void process_http_message( - streambuf_readstream& stream) + dynabuf_readstream& 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 streambuf_readstream +template +class dynabuf_readstream { - static_assert(is_Streambuf::value, - "Streambuf requirements not met"); + static_assert(is_DynamicBuffer::value, + "DynamicBuffer requirements not met"); template 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 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 +#include #endif diff --git a/include/beast/core/impl/basic_streambuf.ipp b/include/beast/core/impl/basic_streambuf.ipp index 23054871..50bb43e0 100644 --- a/include/beast/core/impl/basic_streambuf.ipp +++ b/include/beast/core/impl/basic_streambuf.ipp @@ -8,7 +8,7 @@ #ifndef BEAST_IMPL_BASIC_STREAMBUF_IPP #define BEAST_IMPL_BASIC_STREAMBUF_IPP -#include +#include #include #include #include @@ -527,6 +527,28 @@ basic_streambuf::basic_streambuf( "basic_streambuf: invalid alloc_size"); } +template +std::size_t +basic_streambuf::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 +auto +basic_streambuf:: +data() const -> + const_buffers_type +{ + return const_buffers_type(*this); +} + template auto basic_streambuf::prepare(size_type n) -> @@ -646,14 +668,6 @@ basic_streambuf::commit(size_type n) debug_check(); } -template -auto -basic_streambuf::data() const -> - const_buffers_type -{ - return const_buffers_type(*this); -} - template void basic_streambuf::consume(size_type n) @@ -717,7 +731,8 @@ basic_streambuf::consume(size_type n) template void -basic_streambuf::clear() +basic_streambuf:: +clear() { delete_list(); list_.clear(); @@ -795,21 +810,6 @@ basic_streambuf::delete_list() } } -// Returns the number of bytes which can be -// prepared without causing a memory allocation. -template -std::size_t -basic_streambuf::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 void basic_streambuf::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(512, streambuf.alloc_size_)); @@ -866,7 +866,7 @@ template basic_streambuf& operator<<(basic_streambuf& streambuf, T const& t) { - detail::write_streambuf(streambuf, t); + detail::write_dynabuf(streambuf, t); return streambuf; } diff --git a/include/beast/core/impl/streambuf_readstream.ipp b/include/beast/core/impl/dynabuf_readstream.ipp similarity index 88% rename from include/beast/core/impl/streambuf_readstream.ipp rename to include/beast/core/impl/dynabuf_readstream.ipp index 8a0506d6..a0fbd9b1 100644 --- a/include/beast/core/impl/streambuf_readstream.ipp +++ b/include/beast/core/impl/dynabuf_readstream.ipp @@ -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 #include @@ -16,24 +16,24 @@ namespace beast { -template +template template -class streambuf_readstream< - Stream, Streambuf>::read_some_op +class dynabuf_readstream< + Stream, DynamicBuffer>::read_some_op { using alloc_type = handler_alloc; struct data { - streambuf_readstream& srs; + dynabuf_readstream& srs; MutableBufferSequence bs; Handler h; int state = 0; template data(DeducedHandler&& h_, - streambuf_readstream& srs_, + dynabuf_readstream& srs_, MutableBufferSequence const& bs_) : srs(srs_) , bs(bs_) @@ -50,7 +50,7 @@ public: template read_some_op(DeducedHandler&& h, - streambuf_readstream& srs, Args&&... args) + dynabuf_readstream& srs, Args&&... args) : d_(std::allocate_shared(alloc_type{h}, std::forward(h), srs, std::forward(args)...)) @@ -94,10 +94,10 @@ public: } }; -template +template template void -streambuf_readstream:: +dynabuf_readstream:: read_some_op::operator()( error_code const& ec, std::size_t bytes_transferred) { @@ -155,18 +155,18 @@ read_some_op::operator()( //------------------------------------------------------------------------------ -template +template template -streambuf_readstream:: -streambuf_readstream(Args&&... args) +dynabuf_readstream:: +dynabuf_readstream(Args&&... args) : next_layer_(std::forward(args)...) { } -template +template template auto -streambuf_readstream:: +dynabuf_readstream:: async_write_some(ConstBufferSequence const& buffers, WriteHandler&& handler) -> typename async_completion< @@ -184,10 +184,10 @@ async_write_some(ConstBufferSequence const& buffers, std::forward(handler)); } -template +template template std::size_t -streambuf_readstream:: +dynabuf_readstream:: read_some( MutableBufferSequence const& buffers) { @@ -203,10 +203,10 @@ read_some( return n; } -template +template template std::size_t -streambuf_readstream:: +dynabuf_readstream:: read_some(MutableBufferSequence const& buffers, error_code& ec) { @@ -232,10 +232,10 @@ read_some(MutableBufferSequence const& buffers, return bytes_transferred; } -template +template template auto -streambuf_readstream:: +dynabuf_readstream:: async_read_some( MutableBufferSequence const& buffers, ReadHandler&& handler) -> diff --git a/include/beast/core/static_streambuf.hpp b/include/beast/core/static_streambuf.hpp index 07fa4fc1..2166ba20 100644 --- a/include/beast/core/static_streambuf.hpp +++ b/include/beast/core/static_streambuf.hpp @@ -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. diff --git a/include/beast/core/write_streambuf.hpp b/include/beast/core/write_dynabuf.hpp similarity index 67% rename from include/beast/core/write_streambuf.hpp rename to include/beast/core/write_dynabuf.hpp index 07e7d809..e99c56f0 100644 --- a/include/beast/core/write_streambuf.hpp +++ b/include/beast/core/write_dynabuf.hpp @@ -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 -#include +#include #include #include 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 +template #if GENERATING_DOCS void #else -typename std::enable_if::value>::type +typename std::enable_if::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 diff --git a/include/beast/http/basic_dynabuf_body.hpp b/include/beast/http/basic_dynabuf_body.hpp new file mode 100644 index 00000000..ee84ca53 --- /dev/null +++ b/include/beast/http/basic_dynabuf_body.hpp @@ -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 +#include + +namespace beast { +namespace http { + +/** A message body represented by a @b `DynamicBuffer` + + Meets the requirements of @b `Body`. +*/ +template +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 + explicit + reader(message& 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 + 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 + boost::tribool + operator()(resume_context&&, error_code&, Write&& write) + { + write(body_.data()); + return true; + } + }; +}; + +} // http +} // beast + +#endif diff --git a/include/beast/http/empty_body.hpp b/include/beast/http/empty_body.hpp index 8eb44064..152a71fe 100644 --- a/include/beast/http/empty_body.hpp +++ b/include/beast/http/empty_body.hpp @@ -9,7 +9,6 @@ #define BEAST_HTTP_EMPTY_BODY_HPP #include -#include #include #include #include diff --git a/include/beast/http/impl/read.ipp b/include/beast/http/impl/read.ipp index 0d22a4b5..38c09eb5 100644 --- a/include/beast/http/impl/read.ipp +++ b/include/beast/http/impl/read.ipp @@ -21,7 +21,7 @@ namespace http { namespace detail { template + 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 data(DeducedHandler&& h_, Stream& s_, - Streambuf& sb_, Parser& p_) + DynamicBuffer& sb_, Parser& p_) : s(s_) - , sb(sb_) + , db(sb_) , p(p_) , h(std::forward(h_)) , cont(boost_asio_handler_cont_helpers:: @@ -101,9 +101,9 @@ public: }; template + class DynamicBuffer, class Parser, class Handler> void -parse_op:: +parse_op:: 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 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 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(h_)) , cont(boost_asio_handler_cont_helpers:: @@ -286,11 +286,11 @@ public: } }; -template void -read_op:: +read_op:: 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 +template void parse(SyncReadStream& stream, - Streambuf& streambuf, Parser& parser) + DynamicBuffer& dynabuf, Parser& parser) { static_assert(is_SyncReadStream::value, "SyncReadStream requirements not met"); - static_assert(is_Streambuf::value, - "Streambuf requirements not met"); + static_assert(is_DynamicBuffer::value, + "DynamicBuffer requirements not met"); static_assert(is_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 +template void -parse(SyncReadStream& stream, Streambuf& streambuf, +parse(SyncReadStream& stream, DynamicBuffer& dynabuf, Parser& parser, error_code& ec) { static_assert(is_SyncReadStream::value, "SyncReadStream requirements not met"); - static_assert(is_Streambuf::value, - "Streambuf requirements not met"); + static_assert(is_DynamicBuffer::value, + "DynamicBuffer requirements not met"); static_assert(is_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 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::value, "AsyncReadStream requirements not met"); - static_assert(is_Streambuf::value, - "Streambuf requirements not met"); + static_assert(is_DynamicBuffer::value, + "DynamicBuffer requirements not met"); static_assert(is_Parser::value, "Parser requirements not met"); beast::async_completion completion(handler); - detail::parse_op{ - completion.handler, stream, streambuf, parser}; + completion.handler, stream, dynabuf, parser}; return completion.result.get(); } -template void -read(SyncReadStream& stream, Streambuf& streambuf, +read(SyncReadStream& stream, DynamicBuffer& dynabuf, message_v1& msg) { static_assert(is_SyncReadStream::value, "SyncReadStream requirements not met"); - static_assert(is_Streambuf::value, - "Streambuf requirements not met"); + static_assert(is_DynamicBuffer::value, + "DynamicBuffer requirements not met"); static_assert(is_ReadableBody::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 void -read(SyncReadStream& stream, Streambuf& streambuf, +read(SyncReadStream& stream, DynamicBuffer& dynabuf, message_v1& m, error_code& ec) { static_assert(is_SyncReadStream::value, "SyncReadStream requirements not met"); - static_assert(is_Streambuf::value, - "Streambuf requirements not met"); + static_assert(is_DynamicBuffer::value, + "DynamicBuffer requirements not met"); static_assert(is_ReadableBody::value, "ReadableBody requirements not met"); parser_v1 p; - parse(stream, streambuf, p, ec); + parse(stream, dynabuf, p, ec); if(ec) return; assert(p.complete()); m = p.release(); } -template typename async_completion< ReadHandler, void(error_code)>::result_type -async_read(AsyncReadStream& stream, Streambuf& streambuf, +async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf, message_v1& m, ReadHandler&& handler) { static_assert(is_AsyncReadStream::value, "AsyncReadStream requirements not met"); - static_assert(is_Streambuf::value, - "Streambuf requirements not met"); + static_assert(is_DynamicBuffer::value, + "DynamicBuffer requirements not met"); static_assert(is_ReadableBody::value, "ReadableBody requirements not met"); beast::async_completion completion(handler); - detail::read_op{completion.handler, - stream, streambuf, m}; + stream, dynabuf, m}; return completion.result.get(); } diff --git a/include/beast/http/impl/write.ipp b/include/beast/http/impl/write.ipp index 05f2a908..e06d4ab1 100644 --- a/include/beast/http/impl/write.ipp +++ b/include/beast/http/impl/write.ipp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -32,51 +32,51 @@ namespace http { namespace detail { -template +template void -write_firstline(Streambuf& streambuf, +write_firstline(DynamicBuffer& dynabuf, message_v1 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 +template void -write_firstline(Streambuf& streambuf, +write_firstline(DynamicBuffer& dynabuf, message_v1 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 +template void -write_fields(Streambuf& streambuf, FieldSequence const& fields) +write_fields(DynamicBuffer& dynabuf, FieldSequence const& fields) { - static_assert(is_Streambuf::value, - "Streambuf requirements not met"); + static_assert(is_DynamicBuffer::value, + "DynamicBuffer requirements not met"); //static_assert(is_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 +template 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 const& msg, WriteHandler&& handler) { - static_assert( - is_AsyncWriteStream::value, - "AsyncWriteStream requirements not met"); + static_assert(is_AsyncWriteStream::value, + "AsyncWriteStream requirements not met"); static_assert(is_WritableBody::value, "WritableBody requirements not met"); beast::async_completion #include #include -#include 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 +template 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 +template 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 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 void -read(SyncReadStream& stream, Streambuf& streambuf, +read(SyncReadStream& stream, DynamicBuffer& dynabuf, message_v1& 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 void -read(SyncReadStream& stream, Streambuf& streambuf, +read(SyncReadStream& stream, DynamicBuffer& dynabuf, message_v1& 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 #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& msg, ReadHandler&& handler); diff --git a/include/beast/http/streambuf_body.hpp b/include/beast/http/streambuf_body.hpp index faadf1c1..68a4a4ec 100644 --- a/include/beast/http/streambuf_body.hpp +++ b/include/beast/http/streambuf_body.hpp @@ -8,91 +8,17 @@ #ifndef BEAST_HTTP_STREAMBUF_BODY_HPP #define BEAST_HTTP_STREAMBUF_BODY_HPP -#include -#include +#include #include -#include -#include 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 -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 - explicit - reader(message& 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 - 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 - boost::tribool - operator()(resume_context&&, error_code&, Write&& write) - { - write(body_.data()); - return true; - } - }; -}; - -using streambuf_body = basic_streambuf_body; +using streambuf_body = basic_dynabuf_body; } // http } // beast diff --git a/include/beast/http/string_body.hpp b/include/beast/http/string_body.hpp index c69a626d..76e46a05 100644 --- a/include/beast/http/string_body.hpp +++ b/include/beast/http/string_body.hpp @@ -9,8 +9,7 @@ #define BEAST_HTTP_STRING_BODY_HPP #include -#include -#include +#include #include #include diff --git a/include/beast/websocket/detail/frame.hpp b/include/beast/websocket/detail/frame.hpp index 05955631..0de62d77 100644 --- a/include/beast/websocket/detail/frame.hpp +++ b/include/beast/websocket/detail/frame.hpp @@ -117,11 +117,11 @@ is_valid(close_code::value code) //------------------------------------------------------------------------------ -// Write frame header to streambuf +// Write frame header to dynamic buffer // -template +template 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 +template 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 +template 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 diff --git a/include/beast/websocket/detail/stream_base.hpp b/include/beast/websocket/detail/stream_base.hpp index daecf145..5d66747f 100644 --- a/include/beast/websocket/detail/stream_base.hpp +++ b/include/beast/websocket/detail/stream_base.hpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -107,15 +106,13 @@ protected: void prepare_fh(close_code::value& code); - template + template void - write_close(Streambuf& sb, - close_reason const& rc); + write_close(DynamicBuffer& db, close_reason const& rc); - template + template void - write_ping(Streambuf& sb, opcode op, - ping_data const& data); + write_ping(DynamicBuffer& db, opcode op, ping_data const& data); }; } // detail diff --git a/include/beast/websocket/impl/read_frame_op.ipp b/include/beast/websocket/impl/read_frame_op.ipp index 776d88ca..6102e114 100644 --- a/include/beast/websocket/impl/read_frame_op.ipp +++ b/include/beast/websocket/impl/read_frame_op.ipp @@ -23,7 +23,7 @@ namespace websocket { // processes any received control frames. // template -template +template class stream::read_frame_op { using alloc_type = @@ -35,27 +35,27 @@ class stream::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& ws; frame_info& fi; - Streambuf& sb; + DynamicBuffer& db; Handler h; fb_type fb; - boost::optional smb; + boost::optional dmb; boost::optional fmb; bool cont; int state = 0; template data(DeducedHandler&& h_, stream& ws_, - frame_info& fi_, Streambuf& sb_) + frame_info& fi_, DynamicBuffer& sb_) : ws(ws_) , fi(fi_) - , sb(sb_) + , db(sb_) , h(std::forward(h_)) , cont(boost_asio_handler_cont_helpers:: is_continuation(h)) @@ -127,9 +127,9 @@ public: }; template -template +template void -stream::read_frame_op:: +stream::read_frame_op:: 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 -template +template void -stream::read_frame_op:: +stream::read_frame_op:: 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; diff --git a/include/beast/websocket/impl/read_op.ipp b/include/beast/websocket/impl/read_op.ipp index 89f840e2..e00d19d3 100644 --- a/include/beast/websocket/impl/read_op.ipp +++ b/include/beast/websocket/impl/read_op.ipp @@ -17,7 +17,7 @@ namespace websocket { // read an entire message // template -template +template class stream::read_op { using alloc_type = @@ -27,7 +27,7 @@ class stream::read_op { stream& ws; opcode& op; - Streambuf& sb; + DynamicBuffer& db; Handler h; frame_info fi; bool cont; @@ -36,10 +36,10 @@ class stream::read_op template data(DeducedHandler&& h_, stream& ws_, opcode& op_, - Streambuf& sb_) + DynamicBuffer& sb_) : ws(ws_) , op(op_) - , sb(sb_) + , db(sb_) , h(std::forward(h_)) , cont(boost_asio_handler_cont_helpers:: is_continuation(h)) @@ -98,9 +98,9 @@ public: }; template -template +template void -stream::read_op:: +stream::read_op:: 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; diff --git a/include/beast/websocket/impl/stream.ipp b/include/beast/websocket/impl/stream.ipp index c331cdd3..874081df 100644 --- a/include/beast/websocket/impl/stream.ipp +++ b/include/beast/websocket/impl/stream.ipp @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -94,10 +93,10 @@ stream_base::prepare_fh(close_code::value& code) } } -template +template 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 +template 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:: ping(ping_data const& payload, error_code& ec) { - detail::frame_streambuf sb; + detail::frame_streambuf db; write_ping( - sb, opcode::ping, payload); - boost::asio::write(stream_, sb.data(), ec); + db, opcode::ping, payload); + boost::asio::write(stream_, db.data(), ec); } template @@ -477,31 +476,35 @@ async_ping(ping_data const& payload, PingHandler&& handler) } template -template +template void stream:: -read(opcode& op, Streambuf& streambuf) +read(opcode& op, DynamicBuffer& dynabuf) { static_assert(is_SyncStream::value, "SyncStream requirements not met"); + static_assert(beast::is_DynamicBuffer::value, + "DynamicBuffer requirements not met"); error_code ec; - read(op, streambuf, ec); + read(op, dynabuf, ec); if(ec) throw system_error{ec}; } template -template +template void stream:: -read(opcode& op, Streambuf& streambuf, error_code& ec) +read(opcode& op, DynamicBuffer& dynabuf, error_code& ec) { static_assert(is_SyncStream::value, "SyncStream requirements not met"); + static_assert(beast::is_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 -template +template typename async_completion< ReadHandler, void(error_code)>::result_type stream:: async_read(opcode& op, - Streambuf& streambuf, ReadHandler&& handler) + DynamicBuffer& dynabuf, ReadHandler&& handler) { static_assert(is_AsyncStream::value, "AsyncStream requirements requirements not met"); - static_assert(beast::is_Streambuf::value, - "Streambuf requirements not met"); + static_assert(beast::is_DynamicBuffer::value, + "DynamicBuffer requirements not met"); beast::async_completion< ReadHandler, void(error_code) > completion(handler); - read_op{ - completion.handler, *this, op, streambuf}; + read_op{ + completion.handler, *this, op, dynabuf}; return completion.result.get(); } template -template +template void stream:: -read_frame(frame_info& fi, Streambuf& streambuf) +read_frame(frame_info& fi, DynamicBuffer& dynabuf) { static_assert(is_SyncStream::value, "SyncStream requirements not met"); + static_assert(beast::is_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 -template +template void stream:: -read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec) +read_frame(frame_info& fi, DynamicBuffer& dynabuf, error_code& ec) { static_assert(is_SyncStream::value, "SyncStream requirements not met"); + static_assert(beast::is_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 -template +template typename async_completion< ReadHandler, void(error_code)>::result_type stream:: async_read_frame(frame_info& fi, - Streambuf& streambuf, ReadHandler&& handler) + DynamicBuffer& dynabuf, ReadHandler&& handler) { static_assert(is_AsyncStream::value, "AsyncStream requirements requirements not met"); - static_assert(beast::is_Streambuf::value, - "Streambuf requirements not met"); + static_assert(beast::is_DynamicBuffer::value, + "DynamicBuffer requirements not met"); beast::async_completion< ReadHandler, void(error_code)> completion(handler); - read_frame_op{ - completion.handler, *this, fi, streambuf}; + read_frame_op{ + completion.handler, *this, fi, dynabuf}; return completion.result.get(); } @@ -712,6 +719,9 @@ write(ConstBufferSequence const& buffers) { static_assert(is_SyncStream::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::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) diff --git a/include/beast/websocket/stream.hpp b/include/beast/websocket/stream.hpp index 83699916..dcc5f75d 100644 --- a/include/beast/websocket/stream.hpp +++ b/include/beast/websocket/stream.hpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -78,7 +78,7 @@ struct frame_info @par Concepts @b `AsyncStream`, @b `Decorator`, - @b `Streambuf`, + @b `DynamicBuffer`, @b `SyncStream` */ template @@ -86,7 +86,7 @@ class stream : public detail::stream_base { friend class stream_test; - streambuf_readstream stream_; + dynabuf_readstream 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 void accept(http::request_v1 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 + template 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 + template 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 + template #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 + template 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 + template 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 + template #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 response_op; template class write_op; template class write_frame_op; - template class read_op; - template class read_frame_op; + template class read_op; + template class read_frame_op; void reset(); diff --git a/test/Jamfile b/test/Jamfile index 9cd423b4..508b6e06 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -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 diff --git a/test/core/CMakeLists.txt b/test/core/CMakeLists.txt index 530a60e8..3cc71b05 100644 --- a/test/core/CMakeLists.txt +++ b/test/core/CMakeLists.txt @@ -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 diff --git a/test/core/streambuf_readstream.cpp b/test/core/dynabuf_readstream.cpp similarity index 86% rename from test/core/streambuf_readstream.cpp rename to test/core/dynabuf_readstream.cpp index 9481cb51..97af7455 100644 --- a/test/core/streambuf_readstream.cpp +++ b/test/core/dynabuf_readstream.cpp @@ -6,7 +6,7 @@ // // Test that header file is self-contained. -#include +#include #include #include @@ -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 srs(ios); - streambuf_readstream srs2(std::move(srs)); + dynabuf_readstream srs(ios); + dynabuf_readstream 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 srs(sock); - streambuf_readstream srs2(std::move(srs)); + dynabuf_readstream srs(sock); + dynabuf_readstream 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 diff --git a/test/core/write_streambuf.cpp b/test/core/write_dynabuf.cpp similarity index 84% rename from test/core/write_streambuf.cpp rename to test/core/write_dynabuf.cpp index 15417e31..137ea350 100644 --- a/test/core/write_streambuf.cpp +++ b/test/core/write_dynabuf.cpp @@ -6,14 +6,14 @@ // // Test that header file is self-contained. -#include +#include #include #include 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 diff --git a/test/http/CMakeLists.txt b/test/http/CMakeLists.txt index af46ab20..df4b5ed3 100644 --- a/test/http/CMakeLists.txt +++ b/test/http/CMakeLists.txt @@ -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 diff --git a/test/http/basic_dynabuf_body.cpp b/test/http/basic_dynabuf_body.cpp new file mode 100644 index 00000000..31fbd773 --- /dev/null +++ b/test/http/basic_dynabuf_body.cpp @@ -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 diff --git a/test/http/basic_parser_v1.cpp b/test/http/basic_parser_v1.cpp index b5ef62fd..b1bd2376 100644 --- a/test/http/basic_parser_v1.cpp +++ b/test/http/basic_parser_v1.cpp @@ -11,7 +11,7 @@ #include "message_fuzz.hpp" #include -#include +#include #include #include #include diff --git a/test/http/message_fuzz.hpp b/test/http/message_fuzz.hpp index ef130187..fd29c393 100644 --- a/test/http/message_fuzz.hpp +++ b/test/http/message_fuzz.hpp @@ -8,7 +8,7 @@ #ifndef BEAST_HTTP_TEST_MESSAGE_FUZZ_HPP #define BEAST_HTTP_TEST_MESSAGE_FUZZ_HPP -#include +#include #include #include #include