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