]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/core/flat_buffer.hpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / boost / boost / beast / core / flat_buffer.hpp
1 //
2 // Copyright (c) 2016-2019 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/asio/buffer.hpp>
16 #include <boost/core/empty_value.hpp>
17 #include <limits>
18 #include <memory>
19 #include <type_traits>
20
21 namespace boost {
22 namespace beast {
23
24 /** A dynamic buffer providing buffer sequences of length one.
25
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
32 I/O operations.
33
34 Objects of this type meet the requirements of <em>DynamicBuffer</em>
35 and have the following additional properties:
36
37 @li A mutable buffer sequence representing the readable
38 bytes is returned by @ref data when `this` is non-const.
39
40 @li A configurable maximum buffer size may be set upon
41 construction. Attempts to exceed the buffer size will throw
42 `std::length_error`.
43
44 @li Buffer sequences representing the readable and writable
45 bytes, returned by @ref data and @ref prepare, will have
46 length one.
47
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.
51
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.
56 */
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>>
63 #endif
64 {
65 template<class OtherAlloc>
66 friend class basic_flat_buffer;
67
68 using base_alloc_type = typename
69 detail::allocator_traits<Allocator>::
70 template rebind_alloc<char>;
71
72 static bool constexpr default_nothrow =
73 std::is_nothrow_default_constructible<Allocator>::value;
74
75 using alloc_traits =
76 beast::detail::allocator_traits<base_alloc_type>;
77
78 using pocma = typename
79 alloc_traits::propagate_on_container_move_assignment;
80
81 using pocca = typename
82 alloc_traits::propagate_on_container_copy_assignment;
83
84 static
85 std::size_t
86 dist(char const* first, char const* last) noexcept
87 {
88 return static_cast<std::size_t>(last - first);
89 }
90
91 char* begin_;
92 char* in_;
93 char* out_;
94 char* last_;
95 char* end_;
96 std::size_t max_;
97
98 public:
99 /// The type of allocator used.
100 using allocator_type = Allocator;
101
102 /// Destructor
103 ~basic_flat_buffer();
104
105 /** Constructor
106
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.
110 */
111 basic_flat_buffer() noexcept(default_nothrow);
112
113 /** Constructor
114
115 After construction, @ref capacity will return zero, and
116 @ref max_size will return the specified value of `limit`.
117
118 @param limit The desired maximum size.
119 */
120 explicit
121 basic_flat_buffer(
122 std::size_t limit) noexcept(default_nothrow);
123
124 /** Constructor
125
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.
129
130 @param alloc The allocator to use for the object.
131
132 @esafe
133
134 No-throw guarantee.
135 */
136 explicit
137 basic_flat_buffer(Allocator const& alloc) noexcept;
138
139 /** Constructor
140
141 After construction, @ref capacity will return zero, and
142 @ref max_size will return the specified value of `limit`.
143
144 @param limit The desired maximum size.
145
146 @param alloc The allocator to use for the object.
147
148 @esafe
149
150 No-throw guarantee.
151 */
152 basic_flat_buffer(
153 std::size_t limit,
154 Allocator const& alloc) noexcept;
155
156 /** Move Constructor
157
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.
161
162 Buffer sequences previously obtained from `other` using
163 @ref data or @ref prepare remain valid after the move.
164
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.
168
169 @esafe
170
171 No-throw guarantee.
172 */
173 basic_flat_buffer(basic_flat_buffer&& other) noexcept;
174
175 /** Move Constructor
176
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.
181
182 Buffer sequences previously obtained from `other` using
183 @ref data or @ref prepare become invalid after the move.
184
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.
188
189 @param alloc The allocator to use for the object.
190
191 @throws std::length_error if `other.size()` exceeds the
192 maximum allocation size of `alloc`.
193 */
194 basic_flat_buffer(
195 basic_flat_buffer&& other,
196 Allocator const& alloc);
197
198 /** Copy Constructor
199
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.
203
204 @param other The object to copy from.
205
206 @throws std::length_error if `other.size()` exceeds the
207 maximum allocation size of the allocator.
208 */
209 basic_flat_buffer(basic_flat_buffer const& other);
210
211 /** Copy Constructor
212
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.
216
217 @param other The object to copy from.
218
219 @param alloc The allocator to use for the object.
220
221 @throws std::length_error if `other.size()` exceeds the
222 maximum allocation size of `alloc`.
223 */
224 basic_flat_buffer(
225 basic_flat_buffer const& other,
226 Allocator const& alloc);
227
228 /** Copy Constructor
229
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.
233
234 @param other The object to copy from.
235
236 @throws std::length_error if `other.size()` exceeds the
237 maximum allocation size of the allocator.
238 */
239 template<class OtherAlloc>
240 basic_flat_buffer(
241 basic_flat_buffer<OtherAlloc> const& other)
242 noexcept(default_nothrow);
243
244 /** Copy Constructor
245
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.
249
250 @param other The object to copy from.
251
252 @param alloc The allocator to use for the object.
253
254 @throws std::length_error if `other.size()` exceeds the
255 maximum allocation size of `alloc`.
256 */
257 template<class OtherAlloc>
258 basic_flat_buffer(
259 basic_flat_buffer<OtherAlloc> const& other,
260 Allocator const& alloc);
261
262 /** Move Assignment
263
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.
267
268 Buffer sequences previously obtained from `other` using
269 @ref data or @ref prepare remain valid after the move.
270
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.
274
275 @esafe
276
277 No-throw guarantee.
278 */
279 basic_flat_buffer&
280 operator=(basic_flat_buffer&& other) noexcept;
281
282 /** Copy Assignment
283
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.
287
288 After the copy, `this` will have zero writable bytes.
289
290 @param other The object to copy from.
291
292 @throws std::length_error if `other.size()` exceeds the
293 maximum allocation size of the allocator.
294 */
295 basic_flat_buffer&
296 operator=(basic_flat_buffer const& other);
297
298 /** Copy assignment
299
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.
303
304 After the copy, `this` will have zero writable bytes.
305
306 @param other The object to copy from.
307
308 @throws std::length_error if `other.size()` exceeds the
309 maximum allocation size of the allocator.
310 */
311 template<class OtherAlloc>
312 basic_flat_buffer&
313 operator=(basic_flat_buffer<OtherAlloc> const& other);
314
315 /// Returns a copy of the allocator used.
316 allocator_type
317 get_allocator() const
318 {
319 return this->get();
320 }
321
322 /** Set the maximum allowed capacity
323
324 This function changes the currently configured upper limit
325 on capacity to the specified value.
326
327 @param n The maximum number of bytes ever allowed for capacity.
328
329 @esafe
330
331 No-throw guarantee.
332 */
333 void
334 max_size(std::size_t n) noexcept
335 {
336 max_ = n;
337 }
338
339 /** Guarantee a minimum capacity
340
341 This function adjusts the internal storage (if necessary)
342 to guarantee space for at least `n` bytes.
343
344 Buffer sequences previously obtained using @ref data or
345 @ref prepare become invalid.
346
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.
350
351 @esafe
352
353 Basic guarantee.
354
355 @throws std::length_error if n is larger than the maximum
356 allocation size of the allocator.
357 */
358 void
359 reserve(std::size_t n);
360
361 /** Request the removal of unused capacity.
362
363 This function attempts to reduce @ref capacity()
364 to @ref size(), which may not succeed.
365
366 @esafe
367
368 No-throw guarantee.
369 */
370 void
371 shrink_to_fit() noexcept;
372
373 /** Set the size of the readable and writable bytes to zero.
374
375 This clears the buffer without changing capacity.
376 Buffer sequences previously obtained using @ref data or
377 @ref prepare become invalid.
378
379 @esafe
380
381 No-throw guarantee.
382 */
383 void
384 clear() noexcept;
385
386 /// Exchange two dynamic buffers
387 template<class Alloc>
388 friend
389 void
390 swap(
391 basic_flat_buffer<Alloc>&,
392 basic_flat_buffer<Alloc>&);
393
394 //--------------------------------------------------------------------------
395
396 /// The ConstBufferSequence used to represent the readable bytes.
397 using const_buffers_type = net::const_buffer;
398
399 using mutable_data_type = net::mutable_buffer;
400
401 /// The MutableBufferSequence used to represent the writable bytes.
402 using mutable_buffers_type = net::mutable_buffer;
403
404 /// Returns the number of readable bytes.
405 std::size_t
406 size() const noexcept
407 {
408 return dist(in_, out_);
409 }
410
411 /// Return the maximum number of bytes, both readable and writable, that can ever be held.
412 std::size_t
413 max_size() const noexcept
414 {
415 return max_;
416 }
417
418 /// Return the maximum number of bytes, both readable and writable, that can be held without requiring an allocation.
419 std::size_t
420 capacity() const noexcept
421 {
422 return dist(begin_, end_);
423 }
424
425 /// Returns a constant buffer sequence representing the readable bytes
426 const_buffers_type
427 data() const noexcept
428 {
429 return {in_, dist(in_, out_)};
430 }
431
432 /// Returns a constant buffer sequence representing the readable bytes
433 const_buffers_type
434 cdata() const noexcept
435 {
436 return data();
437 }
438
439 /// Returns a mutable buffer sequence representing the readable bytes
440 mutable_buffers_type
441 data() noexcept
442 {
443 return {in_, dist(in_, out_)};
444 }
445
446 /** Returns a mutable buffer sequence representing writable bytes.
447
448 Returns a mutable buffer sequence representing the writable
449 bytes containing exactly `n` bytes of storage. Memory may be
450 reallocated as needed.
451
452 All buffers sequences previously obtained using
453 @ref data or @ref prepare become invalid.
454
455 @param n The desired number of bytes in the returned buffer
456 sequence.
457
458 @throws std::length_error if `size() + n` exceeds either
459 `max_size()` or the allocator's maximum allocation size.
460
461 @esafe
462
463 Strong guarantee.
464 */
465 mutable_buffers_type
466 prepare(std::size_t n);
467
468 /** Append writable bytes to the readable bytes.
469
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.
474
475 All buffers sequences previously obtained using
476 @ref data or @ref prepare become invalid.
477
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.
481
482 @esafe
483
484 No-throw guarantee.
485 */
486 void
487 commit(std::size_t n) noexcept
488 {
489 out_ += (std::min)(n, dist(out_, last_));
490 }
491
492 /** Remove bytes from beginning of the readable bytes.
493
494 Removes n bytes from the beginning of the readable bytes.
495
496 All buffers sequences previously obtained using
497 @ref data or @ref prepare become invalid.
498
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.
502
503 @esafe
504
505 No-throw guarantee.
506 */
507 void
508 consume(std::size_t n) noexcept;
509
510 private:
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);
521 };
522
523 /// A flat buffer which uses the default allocator.
524 using flat_buffer =
525 basic_flat_buffer<std::allocator<char>>;
526
527 } // beast
528 } // boost
529
530 #include <boost/beast/core/impl/flat_buffer.hpp>
531
532 #endif