diff options
Diffstat (limited to 'boost/beast/core/multi_buffer.hpp')
-rw-r--r-- | boost/beast/core/multi_buffer.hpp | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/boost/beast/core/multi_buffer.hpp b/boost/beast/core/multi_buffer.hpp new file mode 100644 index 0000000000..ee14b419a5 --- /dev/null +++ b/boost/beast/core/multi_buffer.hpp @@ -0,0 +1,322 @@ +// +// 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_MULTI_BUFFER_HPP +#define BOOST_BEAST_MULTI_BUFFER_HPP + +#include <boost/beast/core/detail/config.hpp> +#include <boost/beast/core/detail/allocator.hpp> +#include <boost/beast/core/detail/empty_base_optimization.hpp> +#include <boost/asio/buffer.hpp> +#include <boost/intrusive/list.hpp> +#include <iterator> +#include <limits> +#include <memory> +#include <type_traits> + +namespace boost { +namespace beast { + +/** 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 DynamicBuffer. + + @tparam Allocator The allocator to use for managing memory. +*/ +template<class Allocator> +class basic_multi_buffer +#if ! BOOST_BEAST_DOXYGEN + : private detail::empty_base_optimization< + typename detail::allocator_traits<Allocator>:: + template rebind_alloc<char>> +#endif +{ + using base_alloc_type = typename + detail::allocator_traits<Allocator>:: + template rebind_alloc<char>; + + // Storage for the list of buffers representing the input + // and output sequences. The allocation for each element + // contains `element` followed by raw storage bytes. + class element; + + using alloc_traits = detail::allocator_traits<base_alloc_type>; + using list_type = typename boost::intrusive::make_list<element, + boost::intrusive::constant_time_size<true>>::type; + using iter = typename list_type::iterator; + using const_iter = typename list_type::const_iterator; + + using size_type = typename alloc_traits::size_type; + using const_buffer = boost::asio::const_buffer; + using mutable_buffer = boost::asio::mutable_buffer; + + static_assert(std::is_base_of<std::bidirectional_iterator_tag, + typename std::iterator_traits<iter>::iterator_category>::value, + "BidirectionalIterator requirements not met"); + + static_assert(std::is_base_of<std::bidirectional_iterator_tag, + typename std::iterator_traits<const_iter>::iterator_category>::value, + "BidirectionalIterator requirements not met"); + + std::size_t max_ = + (std::numeric_limits<std::size_t>::max)(); + list_type list_; // list of allocated buffers + iter out_; // element that contains out_pos_ + size_type in_size_ = 0; // size of the input sequence + size_type in_pos_ = 0; // input offset in list_.front() + size_type out_pos_ = 0; // output offset in *out_ + size_type out_end_ = 0; // output end offset in list_.back() + +public: + /// The type of allocator used. + using allocator_type = Allocator; + +#if BOOST_BEAST_DOXYGEN + /// The type used to represent the input sequence as a list of buffers. + using const_buffers_type = implementation_defined; + + /// The type used to represent the output sequence as a list of buffers. + using mutable_buffers_type = implementation_defined; + +#else + class const_buffers_type; + + class mutable_buffers_type; + +#endif + + /// Destructor + ~basic_multi_buffer(); + + /** Constructor + + Upon construction, capacity will be zero. + */ + basic_multi_buffer(); + + /** Constructor. + + @param limit The setting for @ref max_size. + */ + explicit + basic_multi_buffer(std::size_t limit); + + /** Constructor. + + @param alloc The allocator to use. + */ + explicit + basic_multi_buffer(Allocator const& alloc); + + /** Constructor. + + @param limit The setting for @ref max_size. + + @param alloc The allocator to use. + */ + basic_multi_buffer( + std::size_t limit, Allocator const& alloc); + + /** Move constructor + + After the move, `*this` will have an empty output sequence. + + @param other The object to move from. After the move, + The object's state will be as if constructed using + its current allocator and limit. + */ + basic_multi_buffer(basic_multi_buffer&& other); + + /** Move constructor + + After the move, `*this` will have an empty output sequence. + + @param other The object to move from. After the move, + The object's state will be as if constructed using + its current allocator and limit. + + @param alloc The allocator to use. + */ + basic_multi_buffer(basic_multi_buffer&& other, + Allocator const& alloc); + + /** Copy constructor. + + @param other The object to copy from. + */ + basic_multi_buffer(basic_multi_buffer const& other); + + /** Copy constructor + + @param other The object to copy from. + + @param alloc The allocator to use. + */ + basic_multi_buffer(basic_multi_buffer const& other, + Allocator const& alloc); + + /** Copy constructor. + + @param other The object to copy from. + */ + template<class OtherAlloc> + basic_multi_buffer(basic_multi_buffer< + OtherAlloc> const& other); + + /** Copy constructor. + + @param other The object to copy from. + + @param alloc The allocator to use. + */ + template<class OtherAlloc> + basic_multi_buffer(basic_multi_buffer< + OtherAlloc> const& other, allocator_type const& alloc); + + /** Move assignment + + After the move, `*this` will have an empty output sequence. + + @param other The object to move from. After the move, + The object's state will be as if constructed using + its current allocator and limit. + */ + basic_multi_buffer& + operator=(basic_multi_buffer&& other); + + /** Copy assignment + + After the copy, `*this` will have an empty output sequence. + + @param other The object to copy from. + */ + basic_multi_buffer& operator=(basic_multi_buffer const& other); + + /** Copy assignment + + After the copy, `*this` will have an empty output sequence. + + @param other The object to copy from. + */ + template<class OtherAlloc> + basic_multi_buffer& operator=( + basic_multi_buffer<OtherAlloc> const& other); + + /// Returns a copy of the associated allocator. + allocator_type + get_allocator() const + { + return this->member(); + } + + /// 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 max_; + } + + /// 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. + + @note Buffers representing the input sequence acquired prior to + this call remain valid. + */ + mutable_buffers_type + prepare(size_type n); + + /** Move bytes from the output sequence to the input sequence. + + @note Buffers representing the input sequence acquired prior to + this call remain valid. + */ + void + commit(size_type n); + + /// Remove bytes from the input sequence. + void + consume(size_type n); + + template<class Alloc> + friend + void + swap( + basic_multi_buffer<Alloc>& lhs, + basic_multi_buffer<Alloc>& rhs); + +private: + template<class OtherAlloc> + friend class basic_multi_buffer; + + void + delete_list(); + + void + reset(); + + template<class DynamicBuffer> + void + copy_from(DynamicBuffer const& other); + + void + move_assign(basic_multi_buffer& other, std::false_type); + + void + move_assign(basic_multi_buffer& other, std::true_type); + + void + copy_assign(basic_multi_buffer const& other, std::false_type); + + void + copy_assign(basic_multi_buffer const& other, std::true_type); + + void + swap(basic_multi_buffer&); + + void + swap(basic_multi_buffer&, std::true_type); + + void + swap(basic_multi_buffer&, std::false_type); + + void + debug_check() const; +}; + +/// A typical multi buffer +using multi_buffer = basic_multi_buffer<std::allocator<char>>; + +} // beast +} // boost + +#include <boost/beast/core/impl/multi_buffer.ipp> + +#endif |