diff --git a/CHANGELOG.md b/CHANGELOG.md index 54c29616..58eab959 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ Version 198: * flat_buffer improvements * multi_buffer improvements +* static_buffer improvements API Changes: diff --git a/include/boost/beast/core/detail/buffers_pair.hpp b/include/boost/beast/core/detail/buffers_pair.hpp new file mode 100644 index 00000000..7a77aaa5 --- /dev/null +++ b/include/boost/beast/core/detail/buffers_pair.hpp @@ -0,0 +1,90 @@ +// +// Copyright (c) 2018 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_DETAIL_BUFFERS_PAIR_HPP +#define BOOST_BEAST_DETAIL_BUFFERS_PAIR_HPP + +#include +#include +#include + +namespace boost { +namespace beast { +namespace detail { + +template +class buffers_pair +{ + template + friend class buffers_pair; + +public: + // VFALCO: This type is public otherwise + // asio::buffers_iterator won't compile. + using value_type = typename + std::conditional::type; + + using const_iterator = value_type const*; + + buffers_pair() = default; + buffers_pair(buffers_pair const&) = default; + buffers_pair& operator=(buffers_pair const&) = default; + + template< + bool IsMutable_ = IsMutable, + class = typename + std::enable_if::type> + buffers_pair( + buffers_pair const& other) noexcept + : b_{other.b_[0], other.b_[1]} + { + } + + template< + bool IsMutable_ = IsMutable, + class = typename + std::enable_if::type> + buffers_pair& operator=( + buffers_pair const& other) noexcept + { + b_ = {other.b_[0], other.b_[1]}; + return *this; + } + + value_type& + operator[](int i) noexcept + { + BOOST_ASSERT(i >= 0 && i < 2); + return b_[i]; + } + + const_iterator + begin() const noexcept + { + return &b_[0]; + } + + const_iterator + end() const noexcept + { + if(b_[1].size() > 0) + return &b_[2]; + return &b_[1]; + } +private: + value_type b_[2]; +}; + +} // detail +} // beast +} // boost + +#endif diff --git a/include/boost/beast/core/impl/static_buffer.ipp b/include/boost/beast/core/impl/static_buffer.ipp index 72e6584c..ad47173f 100644 --- a/include/boost/beast/core/impl/static_buffer.ipp +++ b/include/boost/beast/core/impl/static_buffer.ipp @@ -21,15 +21,14 @@ namespace boost { namespace beast { -inline static_buffer_base:: -static_buffer_base(void* p, std::size_t size) noexcept +static_buffer_base( + void* p, std::size_t size) noexcept : begin_(static_cast(p)) , capacity_(size) { } -inline auto static_buffer_base:: data() const noexcept -> @@ -50,7 +49,6 @@ data() const noexcept -> return result; } -inline auto static_buffer_base:: data() noexcept -> @@ -71,7 +69,6 @@ data() noexcept -> return result; } -inline auto static_buffer_base:: prepare(std::size_t n) -> @@ -97,7 +94,6 @@ prepare(std::size_t n) -> return result; } -inline void static_buffer_base:: commit(std::size_t n) noexcept @@ -106,7 +102,6 @@ commit(std::size_t n) noexcept out_size_ = 0; } -inline void static_buffer_base:: consume(std::size_t n) noexcept @@ -126,7 +121,6 @@ consume(std::size_t n) noexcept } } -inline void static_buffer_base:: reset(void* p, std::size_t n) noexcept @@ -142,23 +136,21 @@ reset(void* p, std::size_t n) noexcept template static_buffer:: -static_buffer(static_buffer const& other) +static_buffer(static_buffer const& other) noexcept : static_buffer_base(buf_, N) { - using net::buffer_copy; - this->commit(buffer_copy( + this->commit(net::buffer_copy( this->prepare(other.size()), other.data())); } template auto static_buffer:: -operator=(static_buffer const& other) -> +operator=(static_buffer const& other) noexcept -> static_buffer& { - using net::buffer_copy; this->consume(this->size()); - this->commit(buffer_copy( + this->commit(net::buffer_copy( this->prepare(other.size()), other.data())); return *this; } diff --git a/include/boost/beast/core/static_buffer.hpp b/include/boost/beast/core/static_buffer.hpp index a98d5c70..17e23243 100644 --- a/include/boost/beast/core/static_buffer.hpp +++ b/include/boost/beast/core/static_buffer.hpp @@ -11,6 +11,7 @@ #define BOOST_BEAST_STATIC_BUFFER_HPP #include +#include #include #include #include @@ -21,75 +22,7 @@ namespace boost { namespace beast { -namespace detail { - -template -class buffers_pair -{ - template - friend class buffers_pair; - -public: - // VFALCO: This type is public otherwise - // asio::buffers_iterator won't compile. - using value_type = typename - std::conditional::type; - - using const_iterator = - value_type const*; - - buffers_pair() = default; - buffers_pair(buffers_pair const&) = default; - buffers_pair& operator=(buffers_pair const&) = default; - - template< - bool IsMutable_ = IsMutable, - class = typename std::enable_if::type> - buffers_pair(buffers_pair const& other) noexcept - : b_{other.b_[0], other.b_[1]} - { - } - - template< - bool IsMutable_ = IsMutable, - class = typename std::enable_if::type> - buffers_pair& operator=( - buffers_pair const& other) noexcept - { - b_ = {other.b_[0], other.b_[1]}; - return *this; - } - - value_type& - operator[](int i) noexcept - { - BOOST_ASSERT(i >= 0 && i < 2); - return b_[i]; - } - - const_iterator - begin() const noexcept - { - return &b_[0]; - } - - const_iterator - end() const noexcept - { - if(b_[1].size() > 0) - return &b_[2]; - else - return &b_[1]; - } -private: - value_type b_[2]; -}; - -} // detail - -/** A dynamic buffer providing a fixed, circular buffer. +/** A dynamic buffer providing a fixed size, circular buffer. A dynamic buffer encapsulates memory storage that may be automatically resized as required, where the memory is @@ -106,8 +39,8 @@ private: bytes is returned by @ref data when `this` is non-const. @li Buffer sequences representing the readable and writable - bytes, returned by @ref data and @ref prepare, will have - length at most one. + bytes, returned by @ref data and @ref prepare, may have + length up to two. @li All operations execute in constant time. @@ -140,6 +73,7 @@ public: @param size The number of valid bytes pointed to by `p`. */ + inline static_buffer_base(void* p, std::size_t size) noexcept; //-------------------------------------------------------------------------- @@ -181,6 +115,7 @@ public: } /// Returns a constant buffer sequence representing the readable bytes + inline const_buffers_type data() const noexcept; @@ -192,6 +127,7 @@ public: } /// Returns a mutable buffer sequence representing the readable bytes + inline mutable_data_type data() noexcept; @@ -208,7 +144,12 @@ public: sequence. @throws std::length_error if `size() + n` exceeds `max_size()`. + + @par Exception Safety + + Strong guarantee. */ + inline mutable_buffers_type prepare(std::size_t n); @@ -225,7 +166,12 @@ public: @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. */ + inline void commit(std::size_t n) noexcept; @@ -239,7 +185,12 @@ public: @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. */ + inline void consume(std::size_t n) noexcept; @@ -262,19 +213,39 @@ protected: @param p A pointer to valid storage of at least `n` bytes. @param size The number of valid bytes pointed to by `p`. + + @par Exception Safety + + No-throw guarantee. */ + inline void reset(void* p, std::size_t size) noexcept; }; //------------------------------------------------------------------------------ -/** A circular @b DynamicBuffer with a fixed size internal buffer. +/** A dynamic buffer providing a fixed size, circular buffer. - This implements a circular dynamic buffer. Calls to @ref prepare - never require moving memory. The buffer sequences returned may - be up to length two. - Ownership of the underlying storage belongs to the derived class. + A dynamic buffer encapsulates memory storage that may be + automatically resized as required, where the memory is + divided into two regions: readable bytes followed by + writable bytes. 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. + + Objects of this type meet the requirements of @b DynamicBuffer + and have the following additional properties: + + @li A mutable buffer sequence representing the readable + bytes is returned by @ref data when `this` is non-const. + + @li Buffer sequences representing the readable and writable + bytes, returned by @ref data and @ref prepare, may have + length up to two. + + @li All operations execute in constant time. @tparam N The number of bytes in the internal buffer. @@ -291,41 +262,41 @@ class static_buffer : public static_buffer_base public: /// Constructor - static_buffer(static_buffer const&); + static_buffer(static_buffer const&) noexcept; /// Constructor - static_buffer() + static_buffer() noexcept : static_buffer_base(buf_, N) { } /// Assignment - static_buffer& operator=(static_buffer const&); + static_buffer& operator=(static_buffer const&) noexcept; /// Returns the @ref static_buffer_base portion of this object static_buffer_base& - base() + base() noexcept { return *this; } /// Returns the @ref static_buffer_base portion of this object static_buffer_base const& - base() const + base() const noexcept { return *this; } /// Return the maximum sum of the input and output sequence sizes. std::size_t constexpr - max_size() const + max_size() const noexcept { return N; } /// Return the maximum sum of input and output sizes that can be held without an allocation. std::size_t constexpr - capacity() const + capacity() const noexcept { return N; }