diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d1e5c22..a55e5fb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,17 @@ Version 200 * Don't include OpenSSL for core snippets * Tidy up msvc-14 workaround in multi_buffer * buffers_cat fixes and coverage +* Refactor buffers_adaptor + +API Changes: + +* buffers_adaptor is renamed (was buffers_adapter) + +Actions Required: + +* Replace buffers_adapter.hpp with buffers_adaptor.hpp, and + replace buffers_adapter with buffers_adaptor. Or, define + BOOST_BEAST_ALLOW_DEPRECATED -------------------------------------------------------------------------------- diff --git a/doc/qbk/03_core/3_buffers.qbk b/doc/qbk/03_core/3_buffers.qbk index e1397d4e..53ad78c0 100644 --- a/doc/qbk/03_core/3_buffers.qbk +++ b/doc/qbk/03_core/3_buffers.qbk @@ -88,7 +88,7 @@ set of additional implementations of the dynamic buffer concept: [table Dynamic Buffer Implementations [[Name][Description]] [[ - [link beast.ref.boost__beast__buffers_adapter `buffers_adapter`] + [link beast.ref.boost__beast__buffers_adaptor `buffers_adaptor`] ][ This wrapper adapts any __MutableBufferSequence__ into a __DynamicBuffer__ with an upper limit on the total size of the input and diff --git a/doc/qbk/09_releases.qbk b/doc/qbk/09_releases.qbk index 8dbba163..000526a2 100644 --- a/doc/qbk/09_releases.qbk +++ b/doc/qbk/09_releases.qbk @@ -96,7 +96,7 @@ in future versions. * Generated WebSocket masks use a secure PRNG by default -* Improvements to [link beast.ref.boost__beast__buffers_adapter `buffers_adapter`] +* Improvements to [link beast.ref.boost__beast__buffers_adaptor `buffers_adaptor`] * ([issue 1188]) Set "/permissive-" for MSVC builds @@ -134,9 +134,9 @@ in future versions. * Fix [link beast.ref.boost__beast__http__parser `http::parser`] constructor javadoc -* Fix [link beast.ref.boost__beast__buffers_adapter `buffers_adapter`] iterator value type +* Fix [link beast.ref.boost__beast__buffers_adaptor `buffers_adaptor`] iterator value type -* Fix [link beast.ref.boost__beast__buffers_adapter.max_size `buffers_adapter::max_size`] +* Fix [link beast.ref.boost__beast__buffers_adaptor.max_size `buffers_adaptor::max_size`] * Fix [link beast.ref.boost__beast__buffers_prefix `buffers_prefix`] iterator decrement diff --git a/doc/qbk/quickref.xml b/doc/qbk/quickref.xml index 20ee7b2c..44b3c5b2 100644 --- a/doc/qbk/quickref.xml +++ b/doc/qbk/quickref.xml @@ -180,7 +180,7 @@ basic_flat_buffer basic_multi_buffer buffered_read_stream - buffers_adapter + buffers_adaptor buffers_cat_view buffers_prefix_view buffers_suffix diff --git a/include/boost/beast/_experimental/http/impl/icy_stream.hpp b/include/boost/beast/_experimental/http/impl/icy_stream.hpp index 1d4a135c..d7eb6960 100644 --- a/include/boost/beast/_experimental/http/impl/icy_stream.hpp +++ b/include/boost/beast/_experimental/http/impl/icy_stream.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include #include @@ -132,7 +132,7 @@ class icy_stream::read_op struct data { icy_stream& s; - buffers_adapter b; + buffers_adaptor b; bool match = false; data( @@ -234,7 +234,7 @@ operator()( { using iterator = net::buffers_iterator< typename beast::detail::dynamic_buffer_ref< - buffers_adapter>::const_buffers_type>; + buffers_adaptor>::const_buffers_type>; auto& d = *d_; BOOST_ASIO_CORO_REENTER(*this) { @@ -400,8 +400,8 @@ read_some(MutableBufferSequence const& buffers, error_code& ec) "MutableBufferSequence requirements not met"); using iterator = net::buffers_iterator< typename beast::detail::dynamic_buffer_ref< - buffers_adapter>::const_buffers_type>; - buffers_adapter b(buffers); + buffers_adaptor>::const_buffers_type>; + buffers_adaptor b(buffers); if(b.max_size() == 0) { ec = {}; diff --git a/include/boost/beast/core.hpp b/include/boost/beast/core.hpp index ad492e2e..15fc4867 100644 --- a/include/boost/beast/core.hpp +++ b/include/boost/beast/core.hpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/boost/beast/core/buffers_adapter.hpp b/include/boost/beast/core/buffers_adapter.hpp index e545ca9a..a5829f69 100644 --- a/include/boost/beast/core/buffers_adapter.hpp +++ b/include/boost/beast/core/buffers_adapter.hpp @@ -11,216 +11,25 @@ #define BOOST_BEAST_BUFFERS_ADAPTER_HPP #include -#include -#include -#include -#include + +#ifdef BOOST_BEAST_ALLOW_DEPRECATED + +#include namespace boost { namespace beast { -/** Adapts a MutableBufferSequence into a DynamicBuffer. - - This class wraps a MutableBufferSequence to meet the requirements - of DynamicBuffer. Upon construction the input and output sequences - are empty. A copy of the mutable buffer sequence object is stored; however, - ownership of the underlying memory is not transferred. The caller is - responsible for making sure that referenced memory remains valid - for the duration of any operations. - - The size of the mutable buffer sequence determines the maximum - number of bytes which may be prepared and committed. - - @tparam MutableBufferSequence The type of mutable buffer sequence to wrap. -*/ template -class buffers_adapter -{ - static_assert(net::is_mutable_buffer_sequence< - MutableBufferSequence>::value, - "MutableBufferSequence requirements not met"); - - using iter_type = typename - detail::buffer_sequence_iterator< - MutableBufferSequence>::type; - - MutableBufferSequence bs_; - iter_type begin_; - iter_type out_; - iter_type end_; - std::size_t max_size_; - std::size_t in_pos_ = 0; // offset in *begin_ - std::size_t in_size_ = 0; // size of input sequence - std::size_t out_pos_ = 0; // offset in *out_ - std::size_t out_end_ = 0; // output end offset - - template - buffers_adapter(Deduced&& other, - std::size_t nbegin, std::size_t nout, - std::size_t nend) - : bs_(std::forward(other).bs_) - , begin_(std::next(bs_.begin(), nbegin)) - , out_(std::next(bs_.begin(), nout)) - , end_(std::next(bs_.begin(), nend)) - , max_size_(other.max_size_) - , in_pos_(other.in_pos_) - , in_size_(other.in_size_) - , out_pos_(other.out_pos_) - , out_end_(other.out_end_) - { - } - - iter_type end_impl() const; - -public: - /// The type of the underlying mutable buffer sequence - using value_type = MutableBufferSequence; - - /// Move constructor. - buffers_adapter(buffers_adapter&& other); - - /// Copy constructor. - buffers_adapter(buffers_adapter const& other); - - /// Move assignment. - buffers_adapter& operator=(buffers_adapter&& other); - - /// Copy assignment. - buffers_adapter& operator=(buffers_adapter const&); - - /** Construct a buffers adapter. - - @param buffers The mutable buffer sequence to wrap. A copy of - the object will be made, but ownership of the memory is not - transferred. - */ - explicit - buffers_adapter(MutableBufferSequence const& buffers); - - /** Constructor - - This constructs the buffer adapter in-place from - a list of arguments. - - @param args Arguments forwarded to the buffers constructor. - */ - template - explicit - buffers_adapter(boost::in_place_init_t, Args&&... args); - - /// Returns the original mutable buffer sequence - value_type const& - value() const - { - return bs_; - } - - //-------------------------------------------------------------------------- - -#if BOOST_BEAST_DOXYGEN - /// The ConstBufferSequence used to represent the readable bytes. - using const_buffers_type = __implementation_defined__; - - /// The MutableBufferSequence used to represent the writable bytes. - using mutable_buffers_type = __implementation_defined__; - -#else - class const_buffers_type; - class mutable_buffers_type; -#endif - - /// Returns the number of readable bytes. - std::size_t - size() const noexcept - { - return in_size_; - } - - /// Return the maximum number of bytes, both readable and writable, that can ever be held. - std::size_t - max_size() const noexcept - { - return max_size_; - } - - /// Return the maximum number of bytes, both readable and writable, that can be held without requiring an allocation. - std::size_t - capacity() const noexcept - { - return max_size_; - } - - /// Returns a constant buffer sequence representing the readable bytes - const_buffers_type - data() const noexcept; - - /** Returns a mutable buffer sequence representing writable bytes. - - Returns a mutable buffer sequence representing the writable - bytes containing exactly `n` bytes of storage. This function - does not allocate memory. Instead, the storage comes from - the underlying mutable buffer sequence. - - All buffer sequences previously obtained using @ref prepare are - invalidated. Buffer sequences previously obtained using @ref data - remain valid. - - @param n The desired number of bytes in the returned buffer - sequence. - - @throws std::length_error if `size() + n` exceeds `max_size()`. - - @par Exception Safety - - Strong guarantee. - */ - mutable_buffers_type - prepare(std::size_t n); - - /** Append writable bytes to the readable bytes. - - Appends n bytes from the start of the writable bytes to the - end of the readable bytes. The remainder of the writable bytes - are discarded. If n is greater than the number of writable - bytes, all writable bytes are appended to the readable bytes. - - All buffer sequences previously obtained using @ref prepare are - invalidated. Buffer sequences previously obtained using @ref data - remain valid. - - @param n The number of bytes to append. If this number - is greater than the number of writable bytes, all - writable bytes are appended. - - @par Exception Safety - - No-throw guarantee. - */ - void - commit(std::size_t n) noexcept; - - /** Remove bytes from beginning of the readable bytes. - - Removes n bytes from the beginning of the readable bytes. - - All buffers sequences previously obtained using - @ref data or @ref prepare are invalidated. - - @param n The number of bytes to remove. If this number - is greater than the number of readable bytes, all - readable bytes are removed. - - @par Exception Safety - - No-throw guarantee. - */ - void - consume(std::size_t n) noexcept; -}; +using buffers_adapter = buffers_adaptor; } // beast } // boost -#include +#else + +// The new filename is +#error The file is deprecated, define BOOST_BEAST_ALLOW_DEPRECATED to disable this error + +#endif #endif diff --git a/include/boost/beast/core/buffers_adaptor.hpp b/include/boost/beast/core/buffers_adaptor.hpp new file mode 100644 index 00000000..78462962 --- /dev/null +++ b/include/boost/beast/core/buffers_adaptor.hpp @@ -0,0 +1,228 @@ +// +// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/boostorg/beast +// + +#ifndef BOOST_BEAST_BUFFERS_ADAPTOR_HPP +#define BOOST_BEAST_BUFFERS_ADAPTOR_HPP + +#include +#include +#include +#include +#include + +namespace boost { +namespace beast { + +/** Adapts a MutableBufferSequence into a DynamicBuffer. + + This class wraps a MutableBufferSequence to meet the requirements + of DynamicBuffer. Upon construction the input and output sequences + are empty. A copy of the mutable buffer sequence object is stored; however, + ownership of the underlying memory is not transferred. The caller is + responsible for making sure that referenced memory remains valid + for the duration of any operations. + + The size of the mutable buffer sequence determines the maximum + number of bytes which may be prepared and committed. + + @tparam MutableBufferSequence The type of mutable buffer sequence to adapt. +*/ +template +class buffers_adaptor +{ + static_assert(net::is_mutable_buffer_sequence< + MutableBufferSequence>::value, + "MutableBufferSequence requirements not met"); + + using iter_type = typename + detail::buffer_sequence_iterator< + MutableBufferSequence>::type; + + template + class readable_bytes; + + MutableBufferSequence bs_; + iter_type begin_; + iter_type out_; + iter_type end_; + std::size_t max_size_; + std::size_t in_pos_ = 0; // offset in *begin_ + std::size_t in_size_ = 0; // size of input sequence + std::size_t out_pos_ = 0; // offset in *out_ + std::size_t out_end_ = 0; // output end offset + + iter_type end_impl() const; + + buffers_adaptor( + buffers_adaptor const& other, + std::size_t nbegin, + std::size_t nout, + std::size_t nend); + +public: + /// The type of the underlying mutable buffer sequence + using value_type = MutableBufferSequence; + + /** Construct a buffers adaptor. + + @param buffers The mutable buffer sequence to wrap. A copy of + the object will be made, but ownership of the memory is not + transferred. + */ + explicit + buffers_adaptor(MutableBufferSequence const& buffers); + + /** Constructor + + This constructs the buffer adaptor in-place from + a list of arguments. + + @param args Arguments forwarded to the buffers constructor. + */ + template + explicit + buffers_adaptor(boost::in_place_init_t, Args&&... args); + + /// Copy Constructor + buffers_adaptor(buffers_adaptor const& other); + + /// Copy Assignment + buffers_adaptor& operator=(buffers_adaptor const&); + + /// Returns the original mutable buffer sequence + value_type const& + value() const + { + return bs_; + } + + //-------------------------------------------------------------------------- + +#if BOOST_BEAST_DOXYGEN + /// The ConstBufferSequence used to represent the readable bytes. + using const_buffers_type = __implementation_defined__; + + /// The MutableBufferSequence used to represent the readable bytes. + using mutable_data_type = __implementation_defined__; + + /// The MutableBufferSequence used to represent the writable bytes. + using mutable_buffers_type = __implementation_defined__; + +#else + using const_buffers_type = readable_bytes; + using mutable_data_type = readable_bytes; + class mutable_buffers_type; +#endif + + /// Returns the number of readable bytes. + std::size_t + size() const noexcept + { + return in_size_; + } + + /// Return the maximum number of bytes, both readable and writable, that can ever be held. + std::size_t + max_size() const noexcept + { + return max_size_; + } + + /// Return the maximum number of bytes, both readable and writable, that can be held without requiring an allocation. + std::size_t + capacity() const noexcept + { + return max_size_; + } + + /// Returns a constant buffer sequence representing the readable bytes + const_buffers_type + data() const noexcept; + + /// Returns a constant buffer sequence representing the readable bytes + const_buffers_type + cdata() const noexcept + { + return data(); + } + + /// Returns a mutable buffer sequence representing the readable bytes. + mutable_data_type + data() noexcept; + + /** Returns a mutable buffer sequence representing writable bytes. + + Returns a mutable buffer sequence representing the writable + bytes containing exactly `n` bytes of storage. This function + does not allocate memory. Instead, the storage comes from + the underlying mutable buffer sequence. + + All buffer sequences previously obtained using @ref prepare are + invalidated. Buffer sequences previously obtained using @ref data + remain valid. + + @param n The desired number of bytes in the returned buffer + sequence. + + @throws std::length_error if `size() + n` exceeds `max_size()`. + + @par Exception Safety + + Strong guarantee. + */ + mutable_buffers_type + prepare(std::size_t n); + + /** Append writable bytes to the readable bytes. + + Appends n bytes from the start of the writable bytes to the + end of the readable bytes. The remainder of the writable bytes + are discarded. If n is greater than the number of writable + bytes, all writable bytes are appended to the readable bytes. + + All buffer sequences previously obtained using @ref prepare are + invalidated. Buffer sequences previously obtained using @ref data + remain valid. + + @param n The number of bytes to append. If this number + is greater than the number of writable bytes, all + writable bytes are appended. + + @par Exception Safety + + No-throw guarantee. + */ + void + commit(std::size_t n) noexcept; + + /** Remove bytes from beginning of the readable bytes. + + Removes n bytes from the beginning of the readable bytes. + + All buffers sequences previously obtained using + @ref data or @ref prepare are invalidated. + + @param n The number of bytes to remove. If this number + is greater than the number of readable bytes, all + readable bytes are removed. + + @par Exception Safety + + No-throw guarantee. + */ + void + consume(std::size_t n) noexcept; +}; + +} // beast +} // boost + +#include + +#endif diff --git a/include/boost/beast/core/impl/buffers_adapter.hpp b/include/boost/beast/core/impl/buffers_adaptor.hpp similarity index 62% rename from include/boost/beast/core/impl/buffers_adapter.hpp rename to include/boost/beast/core/impl/buffers_adaptor.hpp index 8d7415d6..2ee0c274 100644 --- a/include/boost/beast/core/impl/buffers_adapter.hpp +++ b/include/boost/beast/core/impl/buffers_adaptor.hpp @@ -7,37 +7,84 @@ // Official repository: https://github.com/boostorg/beast // -#ifndef BOOST_BEAST_IMPL_BUFFERS_ADAPTER_IPP -#define BOOST_BEAST_IMPL_BUFFERS_ADAPTER_IPP +#ifndef BOOST_BEAST_IMPL_BUFFERS_ADAPTOR_HPP +#define BOOST_BEAST_IMPL_BUFFERS_ADAPTOR_HPP #include #include +#include #include #include #include #include #include +#include #include namespace boost { namespace beast { +//------------------------------------------------------------------------------ + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1910) +# pragma warning (push) +# pragma warning (disable: 4521) // multiple copy constructors specified +# pragma warning (disable: 4522) // multiple assignment operators specified +#endif + template -class buffers_adapter:: - const_buffers_type +template +class buffers_adaptor:: + readable_bytes { - buffers_adapter const* b_; + buffers_adaptor const* b_; public: - using value_type = net::const_buffer; + using value_type = typename + std::conditional::type; class const_iterator; - const_buffers_type() = delete; - const_buffers_type( - const_buffers_type const&) = default; - const_buffers_type& operator=( - const_buffers_type const&) = default; + readable_bytes() = delete; + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1910) + readable_bytes( + readable_bytes const& other) + : b_(other.b_) + { + } + + readable_bytes& operator=( + readable_bytes const& other) + { + b_ = other.b_; + return *this; + } +#else + readable_bytes( + readable_bytes const&) = default; + readable_bytes& operator=( + readable_bytes const&) = default; +#endif + + template::type> + readable_bytes( + readable_bytes const& other) noexcept + : b_(other.b_) + { + } + + template::type> + readable_bytes& operator=( + readable_bytes const& other) noexcept + { + b_ = other.b_; + return *this; + } const_iterator begin() const; @@ -46,23 +93,34 @@ public: end() const; private: - friend class buffers_adapter; + friend class buffers_adaptor; - const_buffers_type(buffers_adapter const& b) + readable_bytes(buffers_adaptor const& b) : b_(&b) { } }; +#if BOOST_WORKAROUND(BOOST_MSVC, < 1910) +# pragma warning (pop) +#endif + +//------------------------------------------------------------------------------ + template -class buffers_adapter:: - const_buffers_type::const_iterator +template +class buffers_adaptor:: + readable_bytes:: + const_iterator { iter_type it_; - buffers_adapter const* b_ = nullptr; + buffers_adaptor const* b_ = nullptr; public: - using value_type = net::const_buffer; + using value_type = typename + std::conditional::type; using pointer = value_type const*; using reference = value_type; using difference_type = std::ptrdiff_t; @@ -70,28 +128,13 @@ public: std::bidirectional_iterator_tag; const_iterator() = default; - const_iterator(const_iterator&& other) = default; const_iterator(const_iterator const& other) = default; - const_iterator& operator=(const_iterator&& other) = default; const_iterator& operator=(const_iterator const& other) = default; bool operator==(const_iterator const& other) const { - return - (b_ == nullptr) ? - ( - other.b_ == nullptr || - other.it_ == other.b_->end_impl() - ):( - (other.b_ == nullptr) ? - ( - it_ == b_->end_impl() - ): ( - b_ == other.b_ && - it_ == other.it_ - ) - ); + return b_ == other.b_ && it_ == other.it_; } bool @@ -144,10 +187,11 @@ public: } private: - friend class const_buffers_type; + friend class readable_bytes; - const_iterator(buffers_adapter const& b, - iter_type iter) + const_iterator( + buffers_adaptor const& b, + iter_type iter) : it_(iter) , b_(&b) { @@ -155,18 +199,22 @@ private: }; template +template auto -buffers_adapter:: -const_buffers_type::begin() const -> +buffers_adaptor:: +readable_bytes:: +begin() const -> const_iterator { return const_iterator{*b_, b_->begin_}; } template +template auto -buffers_adapter:: -const_buffers_type::end() const -> +buffers_adaptor:: +readable_bytes:: +readable_bytes::end() const -> const_iterator { return const_iterator{*b_, b_->end_impl()}; @@ -175,10 +223,10 @@ const_buffers_type::end() const -> //------------------------------------------------------------------------------ template -class buffers_adapter:: +class buffers_adaptor:: mutable_buffers_type { - buffers_adapter const* b_; + buffers_adaptor const* b_; public: using value_type = net::mutable_buffer; @@ -198,21 +246,21 @@ public: end() const; private: - friend class buffers_adapter; + friend class buffers_adaptor; mutable_buffers_type( - buffers_adapter const& b) + buffers_adaptor const& b) : b_(&b) { } }; template -class buffers_adapter:: +class buffers_adaptor:: mutable_buffers_type::const_iterator { iter_type it_; - buffers_adapter const* b_ = nullptr; + buffers_adaptor const* b_ = nullptr; public: using value_type = net::mutable_buffer; @@ -223,28 +271,13 @@ public: std::bidirectional_iterator_tag; const_iterator() = default; - const_iterator(const_iterator&& other) = default; const_iterator(const_iterator const& other) = default; - const_iterator& operator=(const_iterator&& other) = default; const_iterator& operator=(const_iterator const& other) = default; bool operator==(const_iterator const& other) const { - return - (b_ == nullptr) ? - ( - other.b_ == nullptr || - other.it_ == other.b_->end_ - ):( - (other.b_ == nullptr) ? - ( - it_ == b_->end_ - ): ( - b_ == other.b_ && - it_ == other.it_ - ) - ); + return b_ == other.b_ && it_ == other.it_; } bool @@ -299,7 +332,7 @@ public: private: friend class mutable_buffers_type; - const_iterator(buffers_adapter const& b, + const_iterator(buffers_adaptor const& b, iter_type iter) : it_(iter) , b_(&b) @@ -309,7 +342,7 @@ private: template auto -buffers_adapter:: +buffers_adaptor:: mutable_buffers_type:: begin() const -> const_iterator @@ -319,7 +352,7 @@ begin() const -> template auto -buffers_adapter:: +buffers_adaptor:: mutable_buffers_type:: end() const -> const_iterator @@ -331,7 +364,7 @@ end() const -> template auto -buffers_adapter:: +buffers_adaptor:: end_impl() const -> iter_type { @@ -339,57 +372,75 @@ end_impl() const -> } template -buffers_adapter:: -buffers_adapter(buffers_adapter&& other) - : buffers_adapter(std::move(other), - std::distance(net::buffer_sequence_begin(other.bs_), other.begin_), - std::distance(net::buffer_sequence_begin(other.bs_), other.out_), - std::distance(net::buffer_sequence_begin(other.bs_), other.end_)) +buffers_adaptor:: +buffers_adaptor( + buffers_adaptor const& other, + std::size_t nbegin, + std::size_t nout, + std::size_t nend) + : bs_(other.bs_) + , begin_(std::next(bs_.begin(), nbegin)) + , out_(std::next(bs_.begin(), nout)) + , end_(std::next(bs_.begin(), nend)) + , max_size_(other.max_size_) + , in_pos_(other.in_pos_) + , in_size_(other.in_size_) + , out_pos_(other.out_pos_) + , out_end_(other.out_end_) { } template -buffers_adapter:: -buffers_adapter(buffers_adapter const& other) - : buffers_adapter(other, - std::distance(net::buffer_sequence_begin(other.bs_), other.begin_), - std::distance(net::buffer_sequence_begin(other.bs_), other.out_), - std::distance(net::buffer_sequence_begin(other.bs_), other.end_)) +buffers_adaptor:: +buffers_adaptor(MutableBufferSequence const& bs) + : bs_(bs) + , begin_(net::buffer_sequence_begin(bs_)) + , out_ (net::buffer_sequence_begin(bs_)) + , end_ (net::buffer_sequence_begin(bs_)) + , max_size_( + [&bs] + { + using net::buffer_size; + return buffer_size(bs); + }()) +{ +} + +template +template +buffers_adaptor:: +buffers_adaptor( + boost::in_place_init_t, Args&&... args) + : bs_{std::forward(args)...} + , begin_(net::buffer_sequence_begin(bs_)) + , out_ (net::buffer_sequence_begin(bs_)) + , end_ (net::buffer_sequence_begin(bs_)) + , max_size_(net::buffer_size(bs_)) +{ +} + +template +buffers_adaptor:: +buffers_adaptor(buffers_adaptor const& other) + : buffers_adaptor( + other, + std::distance( + net::buffer_sequence_begin(other.bs_), + other.begin_), + std::distance( + net::buffer_sequence_begin(other.bs_), + other.out_), + std::distance( + net::buffer_sequence_begin(other.bs_), + other.end_)) { } template auto -buffers_adapter:: -operator=(buffers_adapter&& other) -> - buffers_adapter& -{ - auto const nbegin = std::distance( - net::buffer_sequence_begin(other.bs_), - other.begin_); - auto const nout = std::distance( - net::buffer_sequence_begin(other.bs_), - other.out_); - auto const nend = std::distance( - net::buffer_sequence_begin(other.bs_), - other.end_); - bs_ = std::move(other.bs_); - begin_ = std::next(net::buffer_sequence_begin(bs_), nbegin); - out_ = std::next(net::buffer_sequence_begin(bs_), nout); - end_ = std::next(net::buffer_sequence_begin(bs_), nend); - max_size_ = other.max_size_; - in_pos_ = other.in_pos_; - in_size_ = other.in_size_; - out_pos_ = other.out_pos_; - out_end_ = other.out_end_; - return *this; -} - -template -auto -buffers_adapter:: -operator=(buffers_adapter const& other) -> - buffers_adapter& +buffers_adaptor:: +operator=(buffers_adaptor const& other) -> + buffers_adaptor& { auto const nbegin = std::distance( net::buffer_sequence_begin(other.bs_), @@ -401,9 +452,12 @@ operator=(buffers_adapter const& other) -> net::buffer_sequence_begin(other.bs_), other.end_); bs_ = other.bs_; - begin_ = std::next(net::buffer_sequence_begin(bs_), nbegin); - out_ = std::next(net::buffer_sequence_begin(bs_), nout); - end_ = std::next(net::buffer_sequence_begin(bs_), nend); + begin_ = std::next( + net::buffer_sequence_begin(bs_), nbegin); + out_ = std::next( + net::buffer_sequence_begin(bs_), nout); + end_ = std::next( + net::buffer_sequence_begin(bs_), nend); max_size_ = other.max_size_; in_pos_ = other.in_pos_; in_size_ = other.in_size_; @@ -412,47 +466,43 @@ operator=(buffers_adapter const& other) -> return *this; } -template -buffers_adapter:: -buffers_adapter(MutableBufferSequence const& bs) - : bs_(bs) - , begin_(net::buffer_sequence_begin(bs_)) - , out_ (net::buffer_sequence_begin(bs_)) - , end_ (net::buffer_sequence_begin(bs_)) - , max_size_(net::buffer_size(bs_)) -{ -} +// template -template -buffers_adapter:: -buffers_adapter(boost::in_place_init_t, Args&&... args) - : bs_{std::forward(args)...} - , begin_(net::buffer_sequence_begin(bs_)) - , out_ (net::buffer_sequence_begin(bs_)) - , end_ (net::buffer_sequence_begin(bs_)) - , max_size_(net::buffer_size(bs_)) +auto +buffers_adaptor:: +data() const noexcept -> + const_buffers_type { + return const_buffers_type{*this}; } template auto -buffers_adapter:: +buffers_adaptor:: +data() noexcept -> + mutable_data_type +{ + return mutable_data_type{*this}; +} + +template +auto +buffers_adaptor:: prepare(std::size_t n) -> mutable_buffers_type { - using net::buffer_size; end_ = out_; if(end_ != net::buffer_sequence_end(bs_)) { - auto size = buffer_size(*end_) - out_pos_; + auto size = net::buffer_size(*end_) - out_pos_; if(n > size) { n -= size; while(++end_ != net::buffer_sequence_end(bs_)) { - size = buffer_size(*end_); + size = net::buffer_size(*end_); if(n < size) { out_end_ = n; @@ -473,22 +523,13 @@ prepare(std::size_t n) -> } if(n > 0) BOOST_THROW_EXCEPTION(std::length_error{ - "buffer overflow"}); + "buffers_adaptor too long"}); return mutable_buffers_type{*this}; } -template -auto -buffers_adapter:: -data() const noexcept -> - const_buffers_type -{ - return const_buffers_type{*this}; -} - template void -buffers_adapter:: +buffers_adaptor:: commit(std::size_t n) noexcept { if(out_ == end_) @@ -524,7 +565,7 @@ commit(std::size_t n) noexcept template void -buffers_adapter:: +buffers_adaptor:: consume(std::size_t n) noexcept { while(begin_ != out_) diff --git a/test/beast/core/CMakeLists.txt b/test/beast/core/CMakeLists.txt index 4bf45a53..53efbe5e 100644 --- a/test/beast/core/CMakeLists.txt +++ b/test/beast/core/CMakeLists.txt @@ -22,6 +22,7 @@ add_executable (tests-beast-core buffer_traits.cpp buffered_read_stream.cpp buffers_adapter.cpp + buffers_adaptor.cpp buffers_cat.cpp buffers_prefix.cpp buffers_range.cpp @@ -39,9 +40,9 @@ add_executable (tests-beast-core ostream.cpp read_size.cpp span.cpp + static_buffer.cpp static_string.cpp string.cpp - static_buffer.cpp string_param.cpp type_traits.cpp detail_base64.cpp diff --git a/test/beast/core/Jamfile b/test/beast/core/Jamfile index bce23255..c09167b3 100644 --- a/test/beast/core/Jamfile +++ b/test/beast/core/Jamfile @@ -12,6 +12,7 @@ local SOURCES = buffer_traits.cpp buffered_read_stream.cpp buffers_adapter.cpp + buffers_adaptor.cpp buffers_cat.cpp buffers_prefix.cpp buffers_range.cpp diff --git a/test/beast/core/buffer_test.hpp b/test/beast/core/buffer_test.hpp index 8a8933dc..ec428ce4 100644 --- a/test/beast/core/buffer_test.hpp +++ b/test/beast/core/buffer_test.hpp @@ -10,18 +10,101 @@ #ifndef BOOST_BEAST_TEST_BUFFER_TEST_HPP #define BOOST_BEAST_TEST_BUFFER_TEST_HPP +#include +#include +#include #include #include -#include #include #include #include +#include +#include #include #include #include namespace boost { namespace beast { + +//------------------------------------------------------------------------------ + +// VFALCO This is here temporarily + +#define SUITE_EXPECT(test, cond) \ + ((test).expect((cond), __FILE__, __LINE__)) + +#define SUITE_EXPECTS(test, cond, reason) \ + ((cond) ? ((test).pass(), true) \ + : ((test).fail((reason), __FILE__, __LINE__), false)) + +//------------------------------------------------------------------------------ + +/** A MutableBufferSequence for tests, where length is always 3. +*/ +class buffers_triple +{ + net::mutable_buffer b_[3]; + +public: + using value_type = net::mutable_buffer; + using const_iterator = net::mutable_buffer const*; + + buffers_triple( + buffers_triple const&) = default; + buffers_triple& operator=( + buffers_triple const&) = default; + + buffers_triple(char* data, std::size_t size) + { + b_[0] = {data, size/6}; + data += b_[0].size(); + size -= b_[0].size(); + + b_[1] = {data, 2*size/5}; + data += b_[1].size(); + size -= b_[1].size(); + + b_[2] = {data, size}; + + BOOST_ASSERT(b_[0].size() > 0); + BOOST_ASSERT(b_[1].size() > 0); + BOOST_ASSERT(b_[2].size() > 0); + } + + bool + operator==(buffers_triple const& rhs) const noexcept + { + return + b_[0].data() == rhs.b_[0].data() && + b_[0].size() == rhs.b_[0].size() && + b_[1].data() == rhs.b_[1].data() && + b_[1].size() == rhs.b_[1].size() && + b_[2].data() == rhs.b_[2].data() && + b_[2].size() == rhs.b_[2].size(); + } + + bool + operator!=(buffers_triple const& rhs) const noexcept + { + return !(*this == rhs); + } + + const_iterator + begin() const noexcept + { + return &b_[0]; + } + + const_iterator + end() const noexcept + { + return &b_[3]; + } +}; + +//------------------------------------------------------------------------------ + namespace test { template @@ -101,6 +184,397 @@ size_rev_post(ConstBufferSequence const& buffers) } } // test + +//------------------------------------------------------------------------------ + +namespace detail { + +template +void test_mutable_buffers( + unit_test::suite&, + MutableBufferSequence const&, + net::const_buffer) +{ +} + +template +void test_mutable_buffers( + unit_test::suite& test, + MutableBufferSequence const& b, + net::mutable_buffer) +{ + using net::buffer_size; + string_view src = "Hello, world!"; + if(src.size() > buffer_size(b)) + src = {src.data(), buffer_size(b)}; + net::buffer_copy(b, net::const_buffer( + src.data(), src.size())); + SUITE_EXPECT(test, + beast::buffers_to_string(b) == src); +} + +} // detail + +/** Test an instance of a constant or mutable buffer sequence. +*/ +template +void +test_buffer_sequence( + beast::unit_test::suite& test, + ConstBufferSequence const& buffers) +{ + BOOST_STATIC_ASSERT( + net::is_const_buffer_sequence< + ConstBufferSequence>::value); + + using net::buffer_size; + + using iterator = decltype( + net::buffer_sequence_begin(buffers)); + SUITE_EXPECT(test, sizeof(iterator) > 0); + + auto const size = buffer_size(buffers); + SUITE_EXPECT(test, size > 0 ); + + // begin, end + auto const length = std::distance( + net::buffer_sequence_begin(buffers), + net::buffer_sequence_end(buffers)); + SUITE_EXPECT(test, length > 0); + SUITE_EXPECT(test, + net::buffer_sequence_begin(buffers) != + net::buffer_sequence_end(buffers)); + + // copy construction + ConstBufferSequence b1(buffers); + SUITE_EXPECT(test, buffer_size(b1) == size); + + // copy assignment + ConstBufferSequence b2(buffers); + b2 = b1; + SUITE_EXPECT(test, buffer_size(b2) == size); + + // iterators + { + iterator it1{}; + iterator it2{}; + iterator it3 = + net::buffer_sequence_begin(buffers); + iterator it4 = + net::buffer_sequence_end(buffers); + SUITE_EXPECT(test, it1 == it2); + SUITE_EXPECT(test, it1 != it3); + SUITE_EXPECT(test, it3 != it1); + SUITE_EXPECT(test, it1 != it4); + SUITE_EXPECT(test, it4 != it1); + } + + // bidirectional + { + auto const first = + net::buffer_sequence_begin(buffers); + auto const last = + net::buffer_sequence_end(buffers); + std::size_t n, m; + iterator it; + + // pre-increment + m = 0; + n = length; + for(it = first; n--; ++it) + m += net::buffer_size(*it); + SUITE_EXPECT(test, it == last); + SUITE_EXPECT(test, m == size); + + // post-increment + m = 0; + n = length; + for(it = first; n--;) + m += net::buffer_size(*it++); + SUITE_EXPECT(test, it == last); + SUITE_EXPECT(test, m == size); + + // pre-decrement + m = 0; + n = length; + for(it = last; n--;) + m += net::buffer_size(*--it); + SUITE_EXPECT(test, it == first); + SUITE_EXPECT(test, m == size); + + // post-decrement + m = 0; + n = length; + for(it = last; n--;) + { + it--; + m += net::buffer_size(*it); + } + SUITE_EXPECT(test, it == first); + SUITE_EXPECT(test, m == size); + } + + detail::test_mutable_buffers(test, buffers, + buffers_type{}); +} + +//------------------------------------------------------------------------------ + +/** Metafunction to determine if a type meets the requirements of MutableDynamicBuffer +*/ +/* @{ */ +// VFALCO This trait needs tests +template +struct is_mutable_dynamic_buffer + : std::false_type +{ +}; + +template +struct is_mutable_dynamic_buffer() = + std::declval().data(), + std::declval() = + std::declval().cdata(), + std::declval() = + std::declval().data() + ) > > : net::is_dynamic_buffer +{ +}; +/** @} */ + +namespace detail { + +template +void +test_mutable_dynamic_buffer( + unit_test::suite&, + MutableDynamicBuffer const&, + std::false_type) +{ +} + +template +void +test_mutable_dynamic_buffer( + unit_test::suite& test, + MutableDynamicBuffer const& b0, + std::true_type) +{ + using net::buffer_size; + + BOOST_STATIC_ASSERT( + net::is_mutable_buffer_sequence::value); + + string_view src = "Hello, world!"; + if(src.size() > b0.max_size()) + src = {src.data(), b0.max_size()}; + + // modify readable bytes + { + MutableDynamicBuffer b(b0); + auto const mb = b.prepare(src.size()); + using iter_type = net::buffers_iterator; + SUITE_EXPECT(test, buffer_size(mb) == src.size()); + std::fill( + iter_type::begin(mb), + iter_type::end(mb), '*'); + b.commit(src.size()); + SUITE_EXPECT(test, b.size() == src.size()); + SUITE_EXPECT(test, + beast::buffers_to_string(b.data()) == + std::string(src.size(), '*')); + SUITE_EXPECT(test, + beast::buffers_to_string(b.cdata()) == + std::string(src.size(), '*')); + auto const n = net::buffer_copy( + b.data(), net::const_buffer( + src.data(), src.size())); + SUITE_EXPECT(test, n == src.size()); + SUITE_EXPECT(test, + beast::buffers_to_string(b.data()) == src); + SUITE_EXPECT(test, + beast::buffers_to_string(b.cdata()) == src); + } + + // mutable to const sequence conversion + { + MutableDynamicBuffer b(b0); + b.commit(net::buffer_copy( + b.prepare(src.size()), + net::const_buffer(src.data(), src.size()))); + auto mb = b.data(); + auto cb = static_cast< + MutableDynamicBuffer const&>(b).data(); + auto cbc = b.cdata(); + SUITE_EXPECT(test, + beast::buffers_to_string(b.data()) == src); + SUITE_EXPECT(test, + beast::buffers_to_string(b.cdata()) == src); + beast::test_buffer_sequence(test, cb); + beast::test_buffer_sequence(test, cbc); + beast::test_buffer_sequence(test, mb); + { + decltype(mb) mb2(mb); + mb = mb2; + decltype(cb) cb2(cb); + cb = cb2; + decltype(cbc) cbc2(cbc); + cbc = cbc2; + } + { + decltype(cb) cb2(mb); + decltype(cbc) cbc2(mb); + cb2 = mb; + cbc2 = mb; + } + } +} + +} // detail + +/** Test an instance of a dynamic buffer or mutable dynamic buffer. +*/ +template +void +test_dynamic_buffer( + unit_test::suite& test, + DynamicBuffer const& b0) +{ + using net::buffer_size; + + BOOST_STATIC_ASSERT( + net::is_dynamic_buffer::value); + + BOOST_STATIC_ASSERT( + net::is_const_buffer_sequence::value); + + BOOST_STATIC_ASSERT( + net::is_mutable_buffer_sequence::value); + + SUITE_EXPECT(test, b0.size() == 0); + SUITE_EXPECT(test, buffer_size(b0.data()) == 0); + + // n == 0 + { + DynamicBuffer b(b0); + b.commit(1); + SUITE_EXPECT(test, b.size() == 0); + SUITE_EXPECT(test, buffer_size(b.prepare(0)) == 0); + b.commit(0); + SUITE_EXPECT(test, b.size() == 0); + b.commit(1); + SUITE_EXPECT(test, b.size() == 0); + b.commit(b.max_size() + 1); + SUITE_EXPECT(test, b.size() == 0); + b.consume(0); + SUITE_EXPECT(test, b.size() == 0); + b.consume(1); + SUITE_EXPECT(test, b.size() == 0); + b.consume(b.max_size() + 1); + SUITE_EXPECT(test, b.size() == 0); + } + + // max_size + { + DynamicBuffer b(b0); + if(SUITE_EXPECT(test, + b.max_size() + 1 > b.max_size())) + { + try + { + b.prepare(b.max_size() + 1); + test.fail("no exception", __FILE__, __LINE__); + } + catch(std::length_error const&) + { + test.pass(); + } + catch(...) + { + test.fail("wrong exception", __FILE__, __LINE__); + } + } + } + + char buf[13]; + unsigned char k0 = 0; + string_view src(buf, sizeof(buf)); + if(src.size() > b0.max_size()) + src = {src.data(), b0.max_size()}; + SUITE_EXPECT(test, b0.max_size() >= src.size()); + SUITE_EXPECT(test, b0.size() == 0); + SUITE_EXPECT(test, buffer_size(b0.data()) == 0); + auto const make_new_src = + [&buf, &k0, &src] + { + auto k = k0++; + for(std::size_t i = 0; i < src.size(); ++i) + buf[i] = k++; + }; + + // readable / writable buffer sequence tests + { + make_new_src(); + DynamicBuffer b(b0); + auto const& bc(b); + auto const mb = b.prepare(src.size()); + SUITE_EXPECT(test, buffer_size(mb) == src.size()); + beast::test_buffer_sequence(test, mb); + b.commit(net::buffer_copy(mb, + net::const_buffer(src.data(), src.size()))); + SUITE_EXPECT(test, + buffer_size(bc.data()) == src.size()); + beast::test_buffer_sequence(test, bc.data()); + } + + // h = in size + // i = prepare size + // j = commit size + // k = consume size + for(std::size_t h = 1; h <= src.size(); ++h) + { + string_view in(src.data(), h); + for(std::size_t i = 1; i <= in.size(); ++i) { + for(std::size_t j = 1; j <= i + 1; ++j) { + for(std::size_t k = 1; k <= in.size(); ++k) { + { + make_new_src(); + + DynamicBuffer b(b0); + auto const& bc(b); + net::const_buffer cb(in.data(), in.size()); + while(cb.size() > 0) + { + auto const mb = b.prepare( + std::min(i, + b.max_size() - b.size())); + auto const n = net::buffer_copy(mb, + net::const_buffer(cb.data(), + std::min(j, cb.size()))); + b.commit(n); + cb += n; + } + SUITE_EXPECT(test, b.size() == in.size()); + SUITE_EXPECT(test, + buffer_size(bc.data()) == in.size()); + SUITE_EXPECT(test, beast::buffers_to_string( + bc.data()) == in); + while(b.size() > 0) + b.consume(k); + SUITE_EXPECT(test, buffer_size(bc.data()) == 0); + } + } } } + } + + // MutableDynamicBuffer refinement + detail::test_mutable_dynamic_buffer(test, b0, + is_mutable_dynamic_buffer{}); +} + } // beast } // boost diff --git a/test/beast/core/buffers_adapter.cpp b/test/beast/core/buffers_adapter.cpp index 83f7f720..ace415b5 100644 --- a/test/beast/core/buffers_adapter.cpp +++ b/test/beast/core/buffers_adapter.cpp @@ -7,186 +7,17 @@ // Official repository: https://github.com/boostorg/beast // +#ifndef BOOST_BEAST_ALLOW_DEPRECATED +#define BOOST_BEAST_ALLOW_DEPRECATED +#endif + // Test that header file is self-contained. #include -#include "buffer_test.hpp" -#include -#include -#include -#include -#include -#include - namespace boost { namespace beast { -class buffers_adapter_test : public unit_test::suite -{ -public: - void testBuffersAdapter() - { - using net::buffer; - using net::buffer_size; - using net::const_buffer; - using net::mutable_buffer; - char buf[12]; - std::string const s = "Hello, world"; - BEAST_EXPECT(s.size() == sizeof(buf)); - for(std::size_t i = 1; i < 4; ++i) { - for(std::size_t j = 1; j < 4; ++j) { - for(std::size_t x = 1; x < 4; ++x) { - for(std::size_t y = 1; y < 4; ++y) { - for(std::size_t t = 1; t < 4; ++ t) { - for(std::size_t u = 1; u < 4; ++ u) { - std::size_t k = sizeof(buf) - (i + j); - std::size_t z = sizeof(buf) - (x + y); - std::size_t v = sizeof(buf) - (t + u); - { - std::memset(buf, 0, sizeof(buf)); - std::array bs{{ - mutable_buffer{&buf[0], i}, - mutable_buffer{&buf[i], j}, - mutable_buffer{&buf[i+j], k}}}; - buffers_adapter ba(std::move(bs)); - BEAST_EXPECT(ba.max_size() == sizeof(buf)); - { - auto d = ba.prepare(z); - BEAST_EXPECT(buffer_size(d) == z); - } - { - auto d = ba.prepare(0); - BEAST_EXPECT(buffer_size(d) == 0); - } - { - auto d = ba.prepare(y); - BEAST_EXPECT(buffer_size(d) == y); - } - { - auto d = ba.prepare(x); - BEAST_EXPECT(buffer_size(d) == x); - ba.commit(buffer_copy(d, buffer(s.data(), x))); - } - BEAST_EXPECT(ba.size() == x); - BEAST_EXPECT(ba.max_size() == sizeof(buf)); - BEAST_EXPECT(buffer_size(ba.data()) == ba.size()); - { - auto d = ba.prepare(x); - BEAST_EXPECT(buffer_size(d) == x); - } - { - auto d = ba.prepare(0); - BEAST_EXPECT(buffer_size(d) == 0); - } - { - auto d = ba.prepare(z); - BEAST_EXPECT(buffer_size(d) == z); - } - { - auto d = ba.prepare(y); - BEAST_EXPECT(buffer_size(d) == y); - ba.commit(buffer_copy(d, buffer(s.data()+x, y))); - } - ba.commit(1); - BEAST_EXPECT(ba.size() == x + y); - BEAST_EXPECT(ba.max_size() == sizeof(buf)); - BEAST_EXPECT(buffer_size(ba.data()) == ba.size()); - { - auto d = ba.prepare(x); - BEAST_EXPECT(buffer_size(d) == x); - } - { - auto d = ba.prepare(y); - BEAST_EXPECT(buffer_size(d) == y); - } - { - auto d = ba.prepare(0); - BEAST_EXPECT(buffer_size(d) == 0); - } - { - auto d = ba.prepare(z); - BEAST_EXPECT(buffer_size(d) == z); - ba.commit(buffer_copy(d, buffer(s.data()+x+y, z))); - } - ba.commit(2); - BEAST_EXPECT(ba.size() == x + y + z); - BEAST_EXPECT(buffer_size(ba.data()) == ba.size()); - BEAST_EXPECT(buffers_to_string(ba.data()) == s); - ba.consume(t); - { - auto d = ba.prepare(0); - BEAST_EXPECT(buffer_size(d) == 0); - } - BEAST_EXPECT(buffers_to_string(ba.data()) == s.substr(t, std::string::npos)); - ba.consume(u); - BEAST_EXPECT(buffers_to_string(ba.data()) == s.substr(t + u, std::string::npos)); - ba.consume(v); - BEAST_EXPECT(buffers_to_string(ba.data()) == ""); - ba.consume(1); - { - auto d = ba.prepare(0); - BEAST_EXPECT(buffer_size(d) == 0); - } - try - { - ba.prepare(1); - fail(); - } - catch(...) - { - pass(); - } - } - }}}}}} - } - void testCommit() - { - using net::buffer_size; - { - using sb_type = net::streambuf; - sb_type b; - buffers_adapter< - sb_type::mutable_buffers_type> ba(b.prepare(3)); - BEAST_EXPECT(buffer_size(ba.prepare(3)) == 3); - ba.commit(2); - BEAST_EXPECT(buffer_size(ba.data()) == 2); - } - { - using sb_type = beast::multi_buffer; - sb_type b; - b.prepare(3); - buffers_adapter< - sb_type::mutable_buffers_type> ba(b.prepare(8)); - BEAST_EXPECT(buffer_size(ba.prepare(8)) == 8); - ba.commit(2); - BEAST_EXPECT(buffer_size(ba.data()) == 2); - ba.consume(1); - ba.commit(6); - ba.consume(2); - BEAST_EXPECT(buffer_size(ba.data()) == 5); - ba.consume(5); - } - } - - void - testIssue386() - { - using type = net::streambuf; - type buffer; - buffers_adapter< - type::mutable_buffers_type> ba{buffer.prepare(512)}; - read_size(ba, 1024); - } - - void run() override - { - testBuffersAdapter(); - testCommit(); - testIssue386(); - } -}; - -BEAST_DEFINE_TESTSUITE(beast,core,buffers_adapter); +BOOST_STATIC_ASSERT(sizeof(buffers_adapter) > 0); } // beast } // boost diff --git a/test/beast/core/buffers_adaptor.cpp b/test/beast/core/buffers_adaptor.cpp new file mode 100644 index 00000000..5452c48c --- /dev/null +++ b/test/beast/core/buffers_adaptor.cpp @@ -0,0 +1,104 @@ +// +// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/boostorg/beast +// + +// Test that header file is self-contained. +#include + +#include "buffer_test.hpp" + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace beast { + +class buffers_adaptor_test : public unit_test::suite +{ +public: + BOOST_STATIC_ASSERT( + is_mutable_dynamic_buffer< + buffers_adaptor>::value); + + void + testDynamicBuffer() + { + char s[13]; + buffers_triple tb(s, sizeof(s)); + buffers_adaptor b(tb); + test_dynamic_buffer(*this, b); + } + + void + testSpecial() + { + using net::buffer_size; + + char s1[13]; + buffers_triple tb1(s1, sizeof(s1)); + BEAST_EXPECT(buffer_size(tb1) == sizeof(s1)); + + char s2[15]; + buffers_triple tb2(s2, sizeof(s2)); + BEAST_EXPECT(buffer_size(tb2) == sizeof(s2)); + + { + // construction + + buffers_adaptor b1(tb1); + BEAST_EXPECT(b1.value() == tb1); + + buffers_adaptor b2(tb2); + BEAST_EXPECT(b2.value() == tb2); + + buffers_adaptor b3(b2); + BEAST_EXPECT(b3.value() == tb2); + + char s3[15]; + buffers_adaptor b4( + boost::in_place_init, s3, sizeof(s3)); + BEAST_EXPECT(b4.value() == buffers_triple(s3, sizeof(s3))); + + // assignment + + b3 = b1; + BEAST_EXPECT(b3.value() == tb1); + } + } + + void + testIssue386() + { + using type = net::streambuf; + type buffer; + buffers_adaptor< + type::mutable_buffers_type> ba{buffer.prepare(512)}; + read_size(ba, 1024); + } + + void + run() override + { + testDynamicBuffer(); + testSpecial(); + testIssue386(); +#if 0 + testBuffersAdapter(); + testCommit(); +#endif + } +}; + +BEAST_DEFINE_TESTSUITE(beast,core,buffers_adaptor); + +} // beast +} // boost diff --git a/test/beast/experimental/icy_stream.cpp b/test/beast/experimental/icy_stream.cpp index 7af5be44..7560415e 100644 --- a/test/beast/experimental/icy_stream.cpp +++ b/test/beast/experimental/icy_stream.cpp @@ -10,7 +10,7 @@ // Test that header file is self-contained. #include -#include +#include #include #include #include @@ -45,7 +45,7 @@ public: { // sync { - buffers_adapter ba(mbs); + buffers_adaptor ba(mbs); std::memset(p.get(), 0, len); icy_stream is{ioc}; @@ -69,7 +69,7 @@ public: } // async { - buffers_adapter ba(mbs); + buffers_adaptor ba(mbs); std::memset(p.get(), 0, len); icy_stream is{ioc};