2 // Copyright (c) 2016-2019 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)
7 // Official repository: https://github.com/boostorg/beast
10 #ifndef BOOST_BEAST_FLAT_BUFFER_HPP
11 #define BOOST_BEAST_FLAT_BUFFER_HPP
13 #include <boost/beast/core/detail/config.hpp>
14 #include <boost/beast/core/detail/allocator.hpp>
15 #include <boost/asio/buffer.hpp>
16 #include <boost/core/empty_value.hpp>
19 #include <type_traits>
24 /** A dynamic buffer providing buffer sequences of length one.
26 A dynamic buffer encapsulates memory storage that may be
27 automatically resized as required, where the memory is
28 divided into two regions: readable bytes followed by
29 writable bytes. These memory regions are internal to
30 the dynamic buffer, but direct access to the elements
31 is provided to permit them to be efficiently used with
34 Objects of this type meet the requirements of <em>DynamicBuffer</em>
35 and have the following additional properties:
37 @li A mutable buffer sequence representing the readable
38 bytes is returned by @ref data when `this` is non-const.
40 @li A configurable maximum buffer size may be set upon
41 construction. Attempts to exceed the buffer size will throw
44 @li Buffer sequences representing the readable and writable
45 bytes, returned by @ref data and @ref prepare, will have
48 Upon construction, a maximum size for the buffer may be
49 specified. If this limit is exceeded, the `std::length_error`
50 exception will be thrown.
52 @note This class is designed for use with algorithms that
53 take dynamic buffers as parameters, and are optimized
54 for the case where the input sequence or output sequence
55 is stored in a single contiguous buffer.
57 template<class Allocator>
58 class basic_flat_buffer
59 #if ! BOOST_BEAST_DOXYGEN
60 : private boost::empty_value<
61 typename detail::allocator_traits<Allocator>::
62 template rebind_alloc<char>>
65 template<class OtherAlloc>
66 friend class basic_flat_buffer;
68 using base_alloc_type = typename
69 detail::allocator_traits<Allocator>::
70 template rebind_alloc<char>;
72 static bool constexpr default_nothrow =
73 std::is_nothrow_default_constructible<Allocator>::value;
76 beast::detail::allocator_traits<base_alloc_type>;
78 using pocma = typename
79 alloc_traits::propagate_on_container_move_assignment;
81 using pocca = typename
82 alloc_traits::propagate_on_container_copy_assignment;
86 dist(char const* first, char const* last) noexcept
88 return static_cast<std::size_t>(last - first);
99 /// The type of allocator used.
100 using allocator_type = Allocator;
103 ~basic_flat_buffer();
107 After construction, @ref capacity will return zero, and
108 @ref max_size will return the largest value which may
109 be passed to the allocator's `allocate` function.
111 basic_flat_buffer() noexcept(default_nothrow);
115 After construction, @ref capacity will return zero, and
116 @ref max_size will return the specified value of `limit`.
118 @param limit The desired maximum size.
122 std::size_t limit) noexcept(default_nothrow);
126 After construction, @ref capacity will return zero, and
127 @ref max_size will return the largest value which may
128 be passed to the allocator's `allocate` function.
130 @param alloc The allocator to use for the object.
137 basic_flat_buffer(Allocator const& alloc) noexcept;
141 After construction, @ref capacity will return zero, and
142 @ref max_size will return the specified value of `limit`.
144 @param limit The desired maximum size.
146 @param alloc The allocator to use for the object.
154 Allocator const& alloc) noexcept;
158 The container is constructed with the contents of `other`
159 using move semantics. The maximum size will be the same
160 as the moved-from object.
162 Buffer sequences previously obtained from `other` using
163 @ref data or @ref prepare remain valid after the move.
165 @param other The object to move from. After the move, the
166 moved-from object will have zero capacity, zero readable
167 bytes, and zero writable bytes.
173 basic_flat_buffer(basic_flat_buffer&& other) noexcept;
177 Using `alloc` as the allocator for the new container, the
178 contents of `other` are moved. If `alloc != other.get_allocator()`,
179 this results in a copy. The maximum size will be the same
180 as the moved-from object.
182 Buffer sequences previously obtained from `other` using
183 @ref data or @ref prepare become invalid after the move.
185 @param other The object to move from. After the move,
186 the moved-from object will have zero capacity, zero readable
187 bytes, and zero writable bytes.
189 @param alloc The allocator to use for the object.
191 @throws std::length_error if `other.size()` exceeds the
192 maximum allocation size of `alloc`.
195 basic_flat_buffer&& other,
196 Allocator const& alloc);
200 This container is constructed with the contents of `other`
201 using copy semantics. The maximum size will be the same
202 as the copied object.
204 @param other The object to copy from.
206 @throws std::length_error if `other.size()` exceeds the
207 maximum allocation size of the allocator.
209 basic_flat_buffer(basic_flat_buffer const& other);
213 This container is constructed with the contents of `other`
214 using copy semantics and the specified allocator. The maximum
215 size will be the same as the copied object.
217 @param other The object to copy from.
219 @param alloc The allocator to use for the object.
221 @throws std::length_error if `other.size()` exceeds the
222 maximum allocation size of `alloc`.
225 basic_flat_buffer const& other,
226 Allocator const& alloc);
230 This container is constructed with the contents of `other`
231 using copy semantics. The maximum size will be the same
232 as the copied object.
234 @param other The object to copy from.
236 @throws std::length_error if `other.size()` exceeds the
237 maximum allocation size of the allocator.
239 template<class OtherAlloc>
241 basic_flat_buffer<OtherAlloc> const& other)
242 noexcept(default_nothrow);
246 This container is constructed with the contents of `other`
247 using copy semantics. The maximum size will be the same
248 as the copied object.
250 @param other The object to copy from.
252 @param alloc The allocator to use for the object.
254 @throws std::length_error if `other.size()` exceeds the
255 maximum allocation size of `alloc`.
257 template<class OtherAlloc>
259 basic_flat_buffer<OtherAlloc> const& other,
260 Allocator const& alloc);
264 The container is assigned with the contents of `other`
265 using move semantics. The maximum size will be the same
266 as the moved-from object.
268 Buffer sequences previously obtained from `other` using
269 @ref data or @ref prepare remain valid after the move.
271 @param other The object to move from. After the move,
272 the moved-from object will have zero capacity, zero readable
273 bytes, and zero writable bytes.
280 operator=(basic_flat_buffer&& other) noexcept;
284 The container is assigned with the contents of `other`
285 using copy semantics. The maximum size will be the same
286 as the copied object.
288 After the copy, `this` will have zero writable bytes.
290 @param other The object to copy from.
292 @throws std::length_error if `other.size()` exceeds the
293 maximum allocation size of the allocator.
296 operator=(basic_flat_buffer const& other);
300 The container is assigned with the contents of `other`
301 using copy semantics. The maximum size will be the same
302 as the copied object.
304 After the copy, `this` will have zero writable bytes.
306 @param other The object to copy from.
308 @throws std::length_error if `other.size()` exceeds the
309 maximum allocation size of the allocator.
311 template<class OtherAlloc>
313 operator=(basic_flat_buffer<OtherAlloc> const& other);
315 /// Returns a copy of the allocator used.
317 get_allocator() const
322 /** Set the maximum allowed capacity
324 This function changes the currently configured upper limit
325 on capacity to the specified value.
327 @param n The maximum number of bytes ever allowed for capacity.
334 max_size(std::size_t n) noexcept
339 /** Guarantee a minimum capacity
341 This function adjusts the internal storage (if necessary)
342 to guarantee space for at least `n` bytes.
344 Buffer sequences previously obtained using @ref data or
345 @ref prepare become invalid.
347 @param n The minimum number of byte for the new capacity.
348 If this value is greater than the maximum size, then the
349 maximum size will be adjusted upwards to this value.
355 @throws std::length_error if n is larger than the maximum
356 allocation size of the allocator.
359 reserve(std::size_t n);
361 /** Request the removal of unused capacity.
363 This function attempts to reduce @ref capacity()
364 to @ref size(), which may not succeed.
371 shrink_to_fit() noexcept;
373 /** Set the size of the readable and writable bytes to zero.
375 This clears the buffer without changing capacity.
376 Buffer sequences previously obtained using @ref data or
377 @ref prepare become invalid.
386 /// Exchange two dynamic buffers
387 template<class Alloc>
391 basic_flat_buffer<Alloc>&,
392 basic_flat_buffer<Alloc>&);
394 //--------------------------------------------------------------------------
396 /// The ConstBufferSequence used to represent the readable bytes.
397 using const_buffers_type = net::const_buffer;
399 using mutable_data_type = net::mutable_buffer;
401 /// The MutableBufferSequence used to represent the writable bytes.
402 using mutable_buffers_type = net::mutable_buffer;
404 /// Returns the number of readable bytes.
406 size() const noexcept
408 return dist(in_, out_);
411 /// Return the maximum number of bytes, both readable and writable, that can ever be held.
413 max_size() const noexcept
418 /// Return the maximum number of bytes, both readable and writable, that can be held without requiring an allocation.
420 capacity() const noexcept
422 return dist(begin_, end_);
425 /// Returns a constant buffer sequence representing the readable bytes
427 data() const noexcept
429 return {in_, dist(in_, out_)};
432 /// Returns a constant buffer sequence representing the readable bytes
434 cdata() const noexcept
439 /// Returns a mutable buffer sequence representing the readable bytes
443 return {in_, dist(in_, out_)};
446 /** Returns a mutable buffer sequence representing writable bytes.
448 Returns a mutable buffer sequence representing the writable
449 bytes containing exactly `n` bytes of storage. Memory may be
450 reallocated as needed.
452 All buffers sequences previously obtained using
453 @ref data or @ref prepare become invalid.
455 @param n The desired number of bytes in the returned buffer
458 @throws std::length_error if `size() + n` exceeds either
459 `max_size()` or the allocator's maximum allocation size.
466 prepare(std::size_t n);
468 /** Append writable bytes to the readable bytes.
470 Appends n bytes from the start of the writable bytes to the
471 end of the readable bytes. The remainder of the writable bytes
472 are discarded. If n is greater than the number of writable
473 bytes, all writable bytes are appended to the readable bytes.
475 All buffers sequences previously obtained using
476 @ref data or @ref prepare become invalid.
478 @param n The number of bytes to append. If this number
479 is greater than the number of writable bytes, all
480 writable bytes are appended.
487 commit(std::size_t n) noexcept
489 out_ += (std::min)(n, dist(out_, last_));
492 /** Remove bytes from beginning of the readable bytes.
494 Removes n bytes from the beginning of the readable bytes.
496 All buffers sequences previously obtained using
497 @ref data or @ref prepare become invalid.
499 @param n The number of bytes to remove. If this number
500 is greater than the number of readable bytes, all
501 readable bytes are removed.
508 consume(std::size_t n) noexcept;
511 template<class OtherAlloc>
512 void copy_from(basic_flat_buffer<OtherAlloc> const& other);
513 void move_assign(basic_flat_buffer&, std::true_type);
514 void move_assign(basic_flat_buffer&, std::false_type);
515 void copy_assign(basic_flat_buffer const&, std::true_type);
516 void copy_assign(basic_flat_buffer const&, std::false_type);
517 void swap(basic_flat_buffer&);
518 void swap(basic_flat_buffer&, std::true_type);
519 void swap(basic_flat_buffer&, std::false_type);
520 char* alloc(std::size_t n);
523 /// A flat buffer which uses the default allocator.
525 basic_flat_buffer<std::allocator<char>>;
530 #include <boost/beast/core/impl/flat_buffer.hpp>