2 // Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 #ifndef BEAST_STREAMBUF_HPP
9 #define BEAST_STREAMBUF_HPP
11 #include <beast/config.hpp>
12 #include <beast/core/detail/empty_base_optimization.hpp>
13 #include <boost/asio/buffer.hpp>
14 #include <boost/intrusive/list.hpp>
18 #include <type_traits>
22 /** A @b `DynamicBuffer` that uses multiple buffers internally.
24 The implementation uses a sequence of one or more character arrays
25 of varying sizes. Additional character array objects are appended to
26 the sequence to accommodate changes in the size of the character
29 @note Meets the requirements of @b DynamicBuffer.
31 @tparam Allocator The allocator to use for managing memory.
33 template<class Allocator>
36 : private detail::empty_base_optimization<
37 typename std::allocator_traits<Allocator>::
38 template rebind_alloc<char>>
43 /// The type of allocator used.
44 using allocator_type = Allocator;
46 using allocator_type = typename
47 std::allocator_traits<Allocator>::
48 template rebind_alloc<char>;
52 // Storage for the list of buffers representing the input
53 // and output sequences. The allocation for each element
54 // contains `element` followed by raw storage bytes.
57 using alloc_traits = std::allocator_traits<allocator_type>;
58 using list_type = typename boost::intrusive::make_list<element,
59 boost::intrusive::constant_time_size<true>>::type;
60 using iterator = typename list_type::iterator;
61 using const_iterator = typename list_type::const_iterator;
63 using size_type = typename std::allocator_traits<Allocator>::size_type;
64 using const_buffer = boost::asio::const_buffer;
65 using mutable_buffer = boost::asio::mutable_buffer;
67 static_assert(std::is_base_of<std::bidirectional_iterator_tag,
68 typename std::iterator_traits<iterator>::iterator_category>::value,
69 "BidirectionalIterator requirements not met");
71 static_assert(std::is_base_of<std::bidirectional_iterator_tag,
72 typename std::iterator_traits<const_iterator>::iterator_category>::value,
73 "BidirectionalIterator requirements not met");
75 list_type list_; // list of allocated buffers
76 iterator out_; // element that contains out_pos_
77 size_type alloc_size_; // min amount to allocate
78 size_type in_size_ = 0; // size of the input sequence
79 size_type in_pos_ = 0; // input offset in list_.front()
80 size_type out_pos_ = 0; // output offset in *out_
81 size_type out_end_ = 0; // output end offset in list_.back()
85 /// The type used to represent the input sequence as a list of buffers.
86 using const_buffers_type = implementation_defined;
88 /// The type used to represent the output sequence as a list of buffers.
89 using mutable_buffers_type = implementation_defined;
92 class const_buffers_type;
94 class mutable_buffers_type;
101 /** Move constructor.
103 The new object will have the input sequence of
104 the other stream buffer, and an empty output sequence.
106 @note After the move, the moved-from object will have
107 an empty input and output sequence, with no internal
110 basic_streambuf(basic_streambuf&&);
112 /** Move constructor.
114 The new object will have the input sequence of
115 the other stream buffer, and an empty output sequence.
117 @note After the move, the moved-from object will have
118 an empty input and output sequence, with no internal
121 @param alloc The allocator to associate with the
124 basic_streambuf(basic_streambuf&&,
125 allocator_type const& alloc);
129 This object will have the input sequence of
130 the other stream buffer, and an empty output sequence.
132 @note After the move, the moved-from object will have
133 an empty input and output sequence, with no internal
137 operator=(basic_streambuf&&);
139 /** Copy constructor.
141 This object will have a copy of the other stream
142 buffer's input sequence, and an empty output sequence.
144 basic_streambuf(basic_streambuf const&);
146 /** Copy constructor.
148 This object will have a copy of the other stream
149 buffer's input sequence, and an empty output sequence.
151 @param alloc The allocator to associate with the
154 basic_streambuf(basic_streambuf const&,
155 allocator_type const& alloc);
159 This object will have a copy of the other stream
160 buffer's input sequence, and an empty output sequence.
162 basic_streambuf& operator=(basic_streambuf const&);
164 /** Copy constructor.
166 This object will have a copy of the other stream
167 buffer's input sequence, and an empty output sequence.
169 template<class OtherAlloc>
170 basic_streambuf(basic_streambuf<OtherAlloc> const&);
172 /** Copy constructor.
174 This object will have a copy of the other stream
175 buffer's input sequence, and an empty output sequence.
177 @param alloc The allocator to associate with the
180 template<class OtherAlloc>
181 basic_streambuf(basic_streambuf<OtherAlloc> const&,
182 allocator_type const& alloc);
186 This object will have a copy of the other stream
187 buffer's input sequence, and an empty output sequence.
189 template<class OtherAlloc>
190 basic_streambuf& operator=(basic_streambuf<OtherAlloc> const&);
192 /** Construct a stream buffer.
194 @param alloc_size The size of buffer to allocate. This is a
195 soft limit, calls to prepare for buffers exceeding this size
196 will allocate the larger size. The default allocation size
199 @param alloc The allocator to use. If this parameter is
200 unspecified, a default constructed allocator will be used.
203 basic_streambuf(std::size_t alloc_size = 1024,
204 Allocator const& alloc = allocator_type{});
206 /// Returns a copy of the associated allocator.
208 get_allocator() const
210 return this->member();
213 /** Returns the default allocation size.
215 This is the smallest size that the stream buffer will allocate.
216 The size of the allocation can influence capacity, which will
217 affect algorithms that use capacity to efficiently read from
226 /** Set the default allocation size.
228 This is the smallest size that the stream buffer will allocate.
229 The size of the allocation can influence capacity, which will
230 affect algorithms that use capacity to efficiently read from
233 @note This will not affect any already-existing allocations.
235 @param n The number of bytes.
238 alloc_size(std::size_t n)
243 /// Returns the size of the input sequence.
250 /// Returns the permitted maximum sum of the sizes of the input and output sequence.
254 return (std::numeric_limits<std::size_t>::max)();
257 /// Returns the maximum sum of the sizes of the input sequence and output sequence the buffer can hold without requiring reallocation.
261 /** Get a list of buffers that represents the input sequence.
263 @note These buffers remain valid across subsequent calls to `prepare`.
268 /** Get a list of buffers that represents the output sequence, with the given size.
270 @note Buffers representing the input sequence acquired prior to
271 this call remain valid.
274 prepare(size_type n);
276 /** Move bytes from the output sequence to the input sequence.
278 @note Buffers representing the input sequence acquired prior to
279 this call remain valid.
284 /// Remove bytes from the input sequence.
286 consume(size_type n);
288 // Helper for boost::asio::read_until
289 template<class OtherAllocator>
292 read_size_helper(basic_streambuf<
293 OtherAllocator> const& streambuf, std::size_t max_size);
300 move_assign(basic_streambuf& other, std::false_type);
303 move_assign(basic_streambuf& other, std::true_type);
306 copy_assign(basic_streambuf const& other, std::false_type);
309 copy_assign(basic_streambuf const& other, std::true_type);
318 /** A @b `DynamicBuffer` that uses multiple buffers internally.
320 The implementation uses a sequence of one or more character arrays
321 of varying sizes. Additional character array objects are appended to
322 the sequence to accommodate changes in the size of the character
325 @note Meets the requirements of @b `DynamicBuffer`.
327 using streambuf = basic_streambuf<std::allocator<char>>;
329 /** Format output to a @ref basic_streambuf.
331 @param streambuf The @ref basic_streambuf to write to.
333 @param t The object to write.
335 @return A reference to the @ref basic_streambuf.
337 template<class Allocator, class T>
338 basic_streambuf<Allocator>&
339 operator<<(basic_streambuf<Allocator>& streambuf, T const& t);
343 #include <beast/core/impl/streambuf.ipp>