]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/core/impl/flat_buffer.ipp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / beast / core / impl / flat_buffer.ipp
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_IMPL_FLAT_BUFFER_HPP
11 #define BOOST_BEAST_IMPL_FLAT_BUFFER_HPP
12
13 #include <boost/assert.hpp>
14 #include <boost/throw_exception.hpp>
15 #include <stdexcept>
16
17 namespace boost {
18 namespace beast {
19
20 /* Memory is laid out thusly:
21
22 begin_ ..|.. in_ ..|.. out_ ..|.. last_ ..|.. end_
23 */
24
25 template<class Allocator>
26 basic_flat_buffer<Allocator>::
27 ~basic_flat_buffer()
28 {
29 if(begin_)
30 alloc_traits::deallocate(
31 this->member(), begin_, dist(begin_, end_));
32 }
33
34 template<class Allocator>
35 basic_flat_buffer<Allocator>::
36 basic_flat_buffer()
37 : begin_(nullptr)
38 , in_(nullptr)
39 , out_(nullptr)
40 , last_(nullptr)
41 , end_(nullptr)
42 , max_((std::numeric_limits<std::size_t>::max)())
43 {
44 }
45
46 template<class Allocator>
47 basic_flat_buffer<Allocator>::
48 basic_flat_buffer(std::size_t limit)
49 : begin_(nullptr)
50 , in_(nullptr)
51 , out_(nullptr)
52 , last_(nullptr)
53 , end_(nullptr)
54 , max_(limit)
55 {
56 }
57
58 template<class Allocator>
59 basic_flat_buffer<Allocator>::
60 basic_flat_buffer(Allocator const& alloc)
61 : detail::empty_base_optimization<base_alloc_type>(alloc)
62 , begin_(nullptr)
63 , in_(nullptr)
64 , out_(nullptr)
65 , last_(nullptr)
66 , end_(nullptr)
67 , max_((std::numeric_limits<std::size_t>::max)())
68 {
69 }
70
71 template<class Allocator>
72 basic_flat_buffer<Allocator>::
73 basic_flat_buffer(std::size_t limit, Allocator const& alloc)
74 : detail::empty_base_optimization<base_alloc_type>(alloc)
75 , begin_(nullptr)
76 , in_(nullptr)
77 , out_(nullptr)
78 , last_(nullptr)
79 , end_(nullptr)
80 , max_(limit)
81 {
82 }
83
84 template<class Allocator>
85 basic_flat_buffer<Allocator>::
86 basic_flat_buffer(basic_flat_buffer&& other)
87 : detail::empty_base_optimization<base_alloc_type>(
88 std::move(other.member()))
89 , begin_(other.begin_)
90 , in_(other.in_)
91 , out_(other.out_)
92 , last_(out_)
93 , end_(other.end_)
94 , max_(other.max_)
95 {
96 other.begin_ = nullptr;
97 other.in_ = nullptr;
98 other.out_ = nullptr;
99 other.last_ = nullptr;
100 other.end_ = nullptr;
101 }
102
103 template<class Allocator>
104 basic_flat_buffer<Allocator>::
105 basic_flat_buffer(basic_flat_buffer&& other,
106 Allocator const& alloc)
107 : detail::empty_base_optimization<base_alloc_type>(alloc)
108 {
109 if(this->member() != other.member())
110 {
111 begin_ = nullptr;
112 in_ = nullptr;
113 out_ = nullptr;
114 last_ = nullptr;
115 end_ = nullptr;
116 max_ = other.max_;
117 copy_from(other);
118 other.reset();
119 }
120 else
121 {
122 begin_ = other.begin_;
123 in_ = other.in_;
124 out_ = other.out_;
125 last_ = out_;
126 end_ = other.end_;
127 max_ = other.max_;
128 other.begin_ = nullptr;
129 other.in_ = nullptr;
130 other.out_ = nullptr;
131 other.last_ = nullptr;
132 other.end_ = nullptr;
133 }
134 }
135
136 template<class Allocator>
137 basic_flat_buffer<Allocator>::
138 basic_flat_buffer(basic_flat_buffer const& other)
139 : detail::empty_base_optimization<base_alloc_type>(
140 alloc_traits::select_on_container_copy_construction(
141 other.member()))
142 , begin_(nullptr)
143 , in_(nullptr)
144 , out_(nullptr)
145 , last_(nullptr)
146 , end_(nullptr)
147 , max_(other.max_)
148 {
149 copy_from(other);
150 }
151
152 template<class Allocator>
153 basic_flat_buffer<Allocator>::
154 basic_flat_buffer(basic_flat_buffer const& other,
155 Allocator const& alloc)
156 : detail::empty_base_optimization<base_alloc_type>(alloc)
157 , begin_(nullptr)
158 , in_(nullptr)
159 , out_(nullptr)
160 , last_(nullptr)
161 , end_(nullptr)
162 , max_(other.max_)
163 {
164 copy_from(other);
165 }
166
167 template<class Allocator>
168 template<class OtherAlloc>
169 basic_flat_buffer<Allocator>::
170 basic_flat_buffer(
171 basic_flat_buffer<OtherAlloc> const& other)
172 : begin_(nullptr)
173 , in_(nullptr)
174 , out_(nullptr)
175 , last_(nullptr)
176 , end_(nullptr)
177 , max_(other.max_)
178 {
179 copy_from(other);
180 }
181
182 template<class Allocator>
183 template<class OtherAlloc>
184 basic_flat_buffer<Allocator>::
185 basic_flat_buffer(basic_flat_buffer<OtherAlloc> const& other,
186 Allocator const& alloc)
187 : detail::empty_base_optimization<base_alloc_type>(alloc)
188 , begin_(nullptr)
189 , in_(nullptr)
190 , out_(nullptr)
191 , last_(nullptr)
192 , end_(nullptr)
193 , max_(other.max_)
194 {
195 copy_from(other);
196 }
197
198 template<class Allocator>
199 auto
200 basic_flat_buffer<Allocator>::
201 operator=(basic_flat_buffer&& other) ->
202 basic_flat_buffer&
203 {
204 if(this != &other)
205 move_assign(other, std::integral_constant<bool,
206 alloc_traits::propagate_on_container_move_assignment::value>{});
207 return *this;
208 }
209
210 template<class Allocator>
211 auto
212 basic_flat_buffer<Allocator>::
213 operator=(basic_flat_buffer const& other) ->
214 basic_flat_buffer&
215 {
216 if(this != &other)
217 copy_assign(other, std::integral_constant<bool,
218 alloc_traits::propagate_on_container_copy_assignment::value>{});
219 return *this;
220 }
221
222 template<class Allocator>
223 template<class OtherAlloc>
224 auto
225 basic_flat_buffer<Allocator>::
226 operator=(basic_flat_buffer<OtherAlloc> const& other) ->
227 basic_flat_buffer&
228 {
229 reset();
230 max_ = other.max_;
231 copy_from(other);
232 return *this;
233 }
234
235 //------------------------------------------------------------------------------
236
237 template<class Allocator>
238 auto
239 basic_flat_buffer<Allocator>::
240 prepare(std::size_t n) ->
241 mutable_buffers_type
242 {
243 if(n <= dist(out_, end_))
244 {
245 // existing capacity is sufficient
246 last_ = out_ + n;
247 return{out_, n};
248 }
249 auto const len = size();
250 if(n <= capacity() - len)
251 {
252 // after a memmove,
253 // existing capacity is sufficient
254 if(len > 0)
255 std::memmove(begin_, in_, len);
256 in_ = begin_;
257 out_ = in_ + len;
258 last_ = out_ + n;
259 return {out_, n};
260 }
261 // enforce maximum capacity
262 if(n > max_ - len)
263 BOOST_THROW_EXCEPTION(std::length_error{
264 "basic_flat_buffer overflow"});
265 // allocate a new buffer
266 auto const new_size = (std::min<std::size_t>)(
267 max_,
268 (std::max<std::size_t>)(2 * len, len + n));
269 auto const p = alloc_traits::allocate(
270 this->member(), new_size);
271 if(begin_)
272 {
273 BOOST_ASSERT(p);
274 BOOST_ASSERT(in_);
275 std::memcpy(p, in_, len);
276 alloc_traits::deallocate(
277 this->member(), begin_, capacity());
278 }
279 begin_ = p;
280 in_ = begin_;
281 out_ = in_ + len;
282 last_ = out_ + n;
283 end_ = begin_ + new_size;
284 return {out_, n};
285 }
286
287 template<class Allocator>
288 void
289 basic_flat_buffer<Allocator>::
290 consume(std::size_t n)
291 {
292 if(n >= dist(in_, out_))
293 {
294 in_ = begin_;
295 out_ = begin_;
296 return;
297 }
298 in_ += n;
299 }
300
301 template<class Allocator>
302 void
303 basic_flat_buffer<Allocator>::
304 shrink_to_fit()
305 {
306 auto const len = size();
307 if(len == capacity())
308 return;
309 char* p;
310 if(len > 0)
311 {
312 BOOST_ASSERT(begin_);
313 BOOST_ASSERT(in_);
314 p = alloc_traits::allocate(
315 this->member(), len);
316 std::memcpy(p, in_, len);
317 }
318 else
319 {
320 p = nullptr;
321 }
322 alloc_traits::deallocate(
323 this->member(), begin_, dist(begin_, end_));
324 begin_ = p;
325 in_ = begin_;
326 out_ = begin_ + len;
327 last_ = out_;
328 end_ = out_;
329 }
330
331 //------------------------------------------------------------------------------
332
333 template<class Allocator>
334 inline
335 void
336 basic_flat_buffer<Allocator>::
337 reset()
338 {
339 consume(size());
340 shrink_to_fit();
341 }
342
343 template<class Allocator>
344 template<class DynamicBuffer>
345 inline
346 void
347 basic_flat_buffer<Allocator>::
348 copy_from(DynamicBuffer const& buffer)
349 {
350 if(buffer.size() == 0)
351 return;
352 using boost::asio::buffer_copy;
353 commit(buffer_copy(
354 prepare(buffer.size()), buffer.data()));
355 }
356
357 template<class Allocator>
358 inline
359 void
360 basic_flat_buffer<Allocator>::
361 move_assign(basic_flat_buffer& other, std::true_type)
362 {
363 reset();
364 this->member() = std::move(other.member());
365 begin_ = other.begin_;
366 in_ = other.in_;
367 out_ = other.out_;
368 last_ = out_;
369 end_ = other.end_;
370 max_ = other.max_;
371 other.begin_ = nullptr;
372 other.in_ = nullptr;
373 other.out_ = nullptr;
374 other.last_ = nullptr;
375 other.end_ = nullptr;
376 }
377
378 template<class Allocator>
379 inline
380 void
381 basic_flat_buffer<Allocator>::
382 move_assign(basic_flat_buffer& other, std::false_type)
383 {
384 reset();
385 if(this->member() != other.member())
386 {
387 copy_from(other);
388 other.reset();
389 }
390 else
391 {
392 move_assign(other, std::true_type{});
393 }
394 }
395
396 template<class Allocator>
397 inline
398 void
399 basic_flat_buffer<Allocator>::
400 copy_assign(basic_flat_buffer const& other, std::true_type)
401 {
402 reset();
403 max_ = other.max_;
404 this->member() = other.member();
405 copy_from(other);
406 }
407
408 template<class Allocator>
409 inline
410 void
411 basic_flat_buffer<Allocator>::
412 copy_assign(basic_flat_buffer const& other, std::false_type)
413 {
414 reset();
415 max_ = other.max_;
416 copy_from(other);
417 }
418
419 template<class Allocator>
420 inline
421 void
422 basic_flat_buffer<Allocator>::
423 swap(basic_flat_buffer& other)
424 {
425 swap(other, typename
426 alloc_traits::propagate_on_container_swap{});
427 }
428
429 template<class Allocator>
430 inline
431 void
432 basic_flat_buffer<Allocator>::
433 swap(basic_flat_buffer& other, std::true_type)
434 {
435 using std::swap;
436 swap(this->member(), other.member());
437 swap(max_, other.max_);
438 swap(begin_, other.begin_);
439 swap(in_, other.in_);
440 swap(out_, other.out_);
441 last_ = this->out_;
442 other.last_ = other.out_;
443 swap(end_, other.end_);
444 }
445
446 template<class Allocator>
447 inline
448 void
449 basic_flat_buffer<Allocator>::
450 swap(basic_flat_buffer& other, std::false_type)
451 {
452 BOOST_ASSERT(this->member() == other.member());
453 using std::swap;
454 swap(max_, other.max_);
455 swap(begin_, other.begin_);
456 swap(in_, other.in_);
457 swap(out_, other.out_);
458 last_ = this->out_;
459 other.last_ = other.out_;
460 swap(end_, other.end_);
461 }
462
463 template<class Allocator>
464 void
465 swap(
466 basic_flat_buffer<Allocator>& lhs,
467 basic_flat_buffer<Allocator>& rhs)
468 {
469 lhs.swap(rhs);
470 }
471
472 } // beast
473 } // boost
474
475 #endif