]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com) | |
3 | // | |
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) | |
6 | // | |
7 | ||
8 | #ifndef BEAST_FLAT_STREAMBUF_HPP | |
9 | #define BEAST_FLAT_STREAMBUF_HPP | |
10 | ||
11 | #include <beast/config.hpp> | |
12 | #include <beast/core/detail/empty_base_optimization.hpp> | |
13 | #include <boost/asio/buffer.hpp> | |
14 | #include <limits> | |
15 | #include <memory> | |
16 | ||
17 | namespace beast { | |
18 | ||
19 | /** A linear dynamic buffer. | |
20 | ||
21 | Objects of this type meet the requirements of @b DynamicBuffer | |
22 | and offer additional invariants: | |
23 | ||
24 | @li Buffer sequences returned by @ref data and @ref prepare | |
25 | will always be of length one. | |
26 | ||
27 | @li A configurable maximum buffer size may be set upon | |
28 | construction. Attempts to exceed the buffer size will throw | |
29 | `std::length_error`. | |
30 | ||
31 | @note This class is designed for use with algorithms that | |
32 | take dynamic buffers as parameters, and are optimized | |
33 | for the case where the input sequence or output sequence | |
34 | is stored in a single contiguous buffer. | |
35 | */ | |
36 | template<class Allocator> | |
37 | class basic_flat_streambuf | |
38 | #if ! BEAST_DOXYGEN | |
39 | : private detail::empty_base_optimization< | |
40 | typename std::allocator_traits<Allocator>:: | |
41 | template rebind_alloc<char>> | |
42 | #endif | |
43 | { | |
44 | public: | |
45 | #if BEAST_DOXYGEN | |
46 | /// The type of allocator used. | |
47 | using allocator_type = Allocator; | |
48 | #else | |
49 | using allocator_type = typename | |
50 | std::allocator_traits<Allocator>:: | |
51 | template rebind_alloc<char>; | |
52 | #endif | |
53 | ||
54 | private: | |
55 | enum | |
56 | { | |
57 | min_size = 512 | |
58 | }; | |
59 | ||
60 | template<class OtherAlloc> | |
61 | friend class basic_flat_streambuf; | |
62 | ||
63 | using alloc_traits = | |
64 | std::allocator_traits<allocator_type>; | |
65 | ||
66 | static | |
67 | inline | |
68 | std::size_t | |
69 | dist(char const* first, char const* last) | |
70 | { | |
71 | return static_cast<std::size_t>(last - first); | |
72 | } | |
73 | ||
74 | char* p_; | |
75 | char* in_; | |
76 | char* out_; | |
77 | char* last_; | |
78 | char* end_; | |
79 | std::size_t max_; | |
80 | ||
81 | public: | |
82 | /// The type used to represent the input sequence as a list of buffers. | |
83 | using const_buffers_type = boost::asio::const_buffers_1; | |
84 | ||
85 | /// The type used to represent the output sequence as a list of buffers. | |
86 | using mutable_buffers_type = boost::asio::mutable_buffers_1; | |
87 | ||
88 | /// Copy assignment (disallowed). | |
89 | basic_flat_streambuf& | |
90 | operator=(basic_flat_streambuf const&) = delete; | |
91 | ||
92 | /// Destructor. | |
93 | ~basic_flat_streambuf(); | |
94 | ||
95 | /** Move constructor. | |
96 | ||
97 | The new object will have the same input sequence | |
98 | and an empty output sequence. | |
99 | ||
100 | @note After the move, the moved-from object will | |
101 | have a capacity of zero, an empty input sequence, | |
102 | and an empty output sequence. | |
103 | */ | |
104 | basic_flat_streambuf(basic_flat_streambuf&&); | |
105 | ||
106 | /** Move constructor. | |
107 | ||
108 | The new object will have the same input sequence | |
109 | and an empty output sequence. | |
110 | ||
111 | @note After the move, the moved-from object will | |
112 | have a capacity of zero, an empty input sequence, | |
113 | and an empty output sequence. | |
114 | ||
115 | @param alloc The allocator to associate with the | |
116 | stream buffer. | |
117 | */ | |
118 | basic_flat_streambuf(basic_flat_streambuf&&, | |
119 | Allocator const& alloc); | |
120 | ||
121 | /** Copy constructor. | |
122 | ||
123 | The new object will have a copy of the input sequence | |
124 | and an empty output sequence. | |
125 | */ | |
126 | basic_flat_streambuf(basic_flat_streambuf const&); | |
127 | ||
128 | /** Copy constructor. | |
129 | ||
130 | The new object will have a copy of the input sequence | |
131 | and an empty output sequence. | |
132 | ||
133 | @param alloc The allocator to associate with the | |
134 | stream buffer. | |
135 | */ | |
136 | basic_flat_streambuf(basic_flat_streambuf const&, | |
137 | Allocator const& alloc); | |
138 | ||
139 | /** Copy constructor. | |
140 | ||
141 | The new object will have a copy of the input sequence | |
142 | and an empty output sequence. | |
143 | */ | |
144 | template<class OtherAlloc> | |
145 | basic_flat_streambuf( | |
146 | basic_flat_streambuf<OtherAlloc> const&); | |
147 | ||
148 | /** Copy constructor. | |
149 | ||
150 | The new object will have a copy of the input sequence | |
151 | and an empty output sequence. | |
152 | ||
153 | @param alloc The allocator to associate with the | |
154 | stream buffer. | |
155 | */ | |
156 | template<class OtherAlloc> | |
157 | basic_flat_streambuf( | |
158 | basic_flat_streambuf<OtherAlloc> const&, | |
159 | Allocator const& alloc); | |
160 | ||
161 | /** Construct a flat stream buffer. | |
162 | ||
163 | No allocation is performed; the buffer will have | |
164 | empty input and output sequences. | |
165 | ||
166 | @param limit An optional non-zero value specifying the | |
167 | maximum of the sum of the input and output sequence sizes | |
168 | that can be allocated. If unspecified, the largest | |
169 | possible value of `std::size_t` is used. | |
170 | */ | |
171 | explicit | |
172 | basic_flat_streambuf(std::size_t limit = ( | |
173 | std::numeric_limits<std::size_t>::max)()); | |
174 | ||
175 | /** Construct a flat stream buffer. | |
176 | ||
177 | No allocation is performed; the buffer will have | |
178 | empty input and output sequences. | |
179 | ||
180 | @param alloc The allocator to associate with the | |
181 | stream buffer. | |
182 | ||
183 | @param limit An optional non-zero value specifying the | |
184 | maximum of the sum of the input and output sequence sizes | |
185 | that can be allocated. If unspecified, the largest | |
186 | possible value of `std::size_t` is used. | |
187 | */ | |
188 | basic_flat_streambuf(Allocator const& alloc, | |
189 | std::size_t limit = ( | |
190 | std::numeric_limits<std::size_t>::max)()); | |
191 | ||
192 | /// Returns a copy of the associated allocator. | |
193 | allocator_type | |
194 | get_allocator() const | |
195 | { | |
196 | return this->member(); | |
197 | } | |
198 | ||
199 | /// Returns the size of the input sequence. | |
200 | std::size_t | |
201 | size() const | |
202 | { | |
203 | return dist(in_, out_); | |
204 | } | |
205 | ||
206 | /// Return the maximum sum of the input and output sequence sizes. | |
207 | std::size_t | |
208 | max_size() const | |
209 | { | |
210 | return max_; | |
211 | } | |
212 | ||
213 | /// Return the maximum sum of input and output sizes that can be held without an allocation. | |
214 | std::size_t | |
215 | capacity() const | |
216 | { | |
217 | return dist(p_, end_); | |
218 | } | |
219 | ||
220 | /// Get a list of buffers that represent the input sequence. | |
221 | const_buffers_type | |
222 | data() const | |
223 | { | |
224 | return {in_, dist(in_, out_)}; | |
225 | } | |
226 | ||
227 | /** Get a list of buffers that represent the output sequence, with the given size. | |
228 | ||
229 | @throws std::length_error if `size() + n` exceeds `max_size()`. | |
230 | ||
231 | @note All previous buffers sequences obtained from | |
232 | calls to @ref data or @ref prepare are invalidated. | |
233 | */ | |
234 | mutable_buffers_type | |
235 | prepare(std::size_t n); | |
236 | ||
237 | /** Move bytes from the output sequence to the input sequence. | |
238 | ||
239 | @param n The number of bytes to move. If this is larger than | |
240 | the number of bytes in the output sequences, then the entire | |
241 | output sequences is moved. | |
242 | ||
243 | @note All previous buffers sequences obtained from | |
244 | calls to @ref data or @ref prepare are invalidated. | |
245 | */ | |
246 | void | |
247 | commit(std::size_t n) | |
248 | { | |
249 | out_ += (std::min)(n, dist(out_, last_)); | |
250 | } | |
251 | ||
252 | /** Remove bytes from the input sequence. | |
253 | ||
254 | If `n` is greater than the number of bytes in the input | |
255 | sequence, all bytes in the input sequence are removed. | |
256 | ||
257 | @note All previous buffers sequences obtained from | |
258 | calls to @ref data or @ref prepare are invalidated. | |
259 | */ | |
260 | void | |
261 | consume(std::size_t n); | |
262 | ||
263 | /** Reserve space in the stream. | |
264 | ||
265 | This reallocates the buffer if necessary. | |
266 | ||
267 | @note All previous buffers sequences obtained from | |
268 | calls to @ref data or @ref prepare are invalidated. | |
269 | ||
270 | @param n The number of bytes to reserve. Upon success, | |
271 | the capacity will be at least `n`. | |
272 | ||
273 | @throws std::length_error if `n` exceeds `max_size()`. | |
274 | */ | |
275 | void | |
276 | reserve(std::size_t n); | |
277 | ||
278 | /** Reallocate the buffer to fit the input sequence. | |
279 | ||
280 | @note All previous buffers sequences obtained from | |
281 | calls to @ref data or @ref prepare are invalidated. | |
282 | */ | |
283 | void | |
284 | shrink_to_fit(); | |
285 | ||
286 | // Helper for boost::asio::read_until | |
287 | template<class OtherAlloc> | |
288 | friend | |
289 | std::size_t | |
290 | read_size_helper(basic_flat_streambuf< | |
291 | OtherAlloc> const&, std::size_t); | |
292 | ||
293 | private: | |
294 | void | |
295 | move_from(basic_flat_streambuf& other); | |
296 | ||
297 | template<class OtherAlloc> | |
298 | void | |
299 | copy_from(basic_flat_streambuf< | |
300 | OtherAlloc> const& other); | |
301 | }; | |
302 | ||
303 | using flat_streambuf = | |
304 | basic_flat_streambuf<std::allocator<char>>; | |
305 | ||
306 | } // beast | |
307 | ||
308 | #include <beast/core/impl/flat_streambuf.ipp> | |
309 | ||
310 | #endif |