]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/core/impl/buffers_adaptor.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / beast / core / impl / buffers_adaptor.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_IMPL_BUFFERS_ADAPTOR_HPP
11 #define BOOST_BEAST_IMPL_BUFFERS_ADAPTOR_HPP
12
13 #include <boost/beast/core/buffer_traits.hpp>
14 #include <boost/asio/buffer.hpp>
15 #include <boost/config/workaround.hpp>
16 #include <boost/throw_exception.hpp>
17 #include <algorithm>
18 #include <cstring>
19 #include <iterator>
20 #include <stdexcept>
21 #include <type_traits>
22 #include <utility>
23
24 namespace boost {
25 namespace beast {
26
27 //------------------------------------------------------------------------------
28
29 #if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
30 # pragma warning (push)
31 # pragma warning (disable: 4521) // multiple copy constructors specified
32 # pragma warning (disable: 4522) // multiple assignment operators specified
33 #endif
34
35 template<class MutableBufferSequence>
36 template<bool isMutable>
37 class buffers_adaptor<MutableBufferSequence>::
38 readable_bytes
39 {
40 buffers_adaptor const* b_;
41
42 public:
43 using value_type = typename
44 std::conditional<isMutable,
45 net::mutable_buffer,
46 net::const_buffer>::type;
47
48 class const_iterator;
49
50 readable_bytes() = delete;
51
52 #if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
53 readable_bytes(
54 readable_bytes const& other)
55 : b_(other.b_)
56 {
57 }
58
59 readable_bytes& operator=(
60 readable_bytes const& other)
61 {
62 b_ = other.b_;
63 return *this;
64 }
65 #else
66 readable_bytes(
67 readable_bytes const&) = default;
68 readable_bytes& operator=(
69 readable_bytes const&) = default;
70 #endif
71
72 template<bool isMutable_ = isMutable, class =
73 typename std::enable_if<! isMutable_>::type>
74 readable_bytes(
75 readable_bytes<true> const& other) noexcept
76 : b_(other.b_)
77 {
78 }
79
80 template<bool isMutable_ = isMutable, class =
81 typename std::enable_if<! isMutable_>::type>
82 readable_bytes& operator=(
83 readable_bytes<true> const& other) noexcept
84 {
85 b_ = other.b_;
86 return *this;
87 }
88
89 const_iterator
90 begin() const;
91
92 const_iterator
93 end() const;
94
95 private:
96 friend class buffers_adaptor;
97
98 readable_bytes(buffers_adaptor const& b)
99 : b_(&b)
100 {
101 }
102 };
103
104 #if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
105 # pragma warning (pop)
106 #endif
107
108 //------------------------------------------------------------------------------
109
110 template<class MutableBufferSequence>
111 template<bool isMutable>
112 class buffers_adaptor<MutableBufferSequence>::
113 readable_bytes<isMutable>::
114 const_iterator
115 {
116 iter_type it_{};
117 buffers_adaptor const* b_ = nullptr;
118
119 public:
120 using value_type = typename
121 std::conditional<isMutable,
122 net::mutable_buffer,
123 net::const_buffer>::type;
124 using pointer = value_type const*;
125 using reference = value_type;
126 using difference_type = std::ptrdiff_t;
127 using iterator_category =
128 std::bidirectional_iterator_tag;
129
130 const_iterator() = default;
131 const_iterator(const_iterator const& other) = default;
132 const_iterator& operator=(const_iterator const& other) = default;
133
134 bool
135 operator==(const_iterator const& other) const
136 {
137 return b_ == other.b_ && it_ == other.it_;
138 }
139
140 bool
141 operator!=(const_iterator const& other) const
142 {
143 return !(*this == other);
144 }
145
146 reference
147 operator*() const
148 {
149 value_type const b = *it_;
150 return value_type{b.data(),
151 (b_->out_ == net::buffer_sequence_end(b_->bs_) ||
152 it_ != b_->out_) ? b.size() : b_->out_pos_} +
153 (it_ == b_->begin_ ? b_->in_pos_ : 0);
154 }
155
156 pointer
157 operator->() const = delete;
158
159 const_iterator&
160 operator++()
161 {
162 ++it_;
163 return *this;
164 }
165
166 const_iterator
167 operator++(int)
168 {
169 auto temp = *this;
170 ++(*this);
171 return temp;
172 }
173
174 const_iterator&
175 operator--()
176 {
177 --it_;
178 return *this;
179 }
180
181 const_iterator
182 operator--(int)
183 {
184 auto temp = *this;
185 --(*this);
186 return temp;
187 }
188
189 private:
190 friend class readable_bytes;
191
192 const_iterator(
193 buffers_adaptor const& b,
194 iter_type iter)
195 : it_(iter)
196 , b_(&b)
197 {
198 }
199 };
200
201 template<class MutableBufferSequence>
202 template<bool isMutable>
203 auto
204 buffers_adaptor<MutableBufferSequence>::
205 readable_bytes<isMutable>::
206 begin() const ->
207 const_iterator
208 {
209 return const_iterator{*b_, b_->begin_};
210 }
211
212 template<class MutableBufferSequence>
213 template<bool isMutable>
214 auto
215 buffers_adaptor<MutableBufferSequence>::
216 readable_bytes<isMutable>::
217 readable_bytes::end() const ->
218 const_iterator
219 {
220 return const_iterator{*b_, b_->end_impl()};
221 }
222
223 //------------------------------------------------------------------------------
224
225 template<class MutableBufferSequence>
226 class buffers_adaptor<MutableBufferSequence>::
227 mutable_buffers_type
228 {
229 buffers_adaptor const* b_;
230
231 public:
232 using value_type = net::mutable_buffer;
233
234 class const_iterator;
235
236 mutable_buffers_type() = delete;
237 mutable_buffers_type(
238 mutable_buffers_type const&) = default;
239 mutable_buffers_type& operator=(
240 mutable_buffers_type const&) = default;
241
242 const_iterator
243 begin() const;
244
245 const_iterator
246 end() const;
247
248 private:
249 friend class buffers_adaptor;
250
251 mutable_buffers_type(
252 buffers_adaptor const& b)
253 : b_(&b)
254 {
255 }
256 };
257
258 template<class MutableBufferSequence>
259 class buffers_adaptor<MutableBufferSequence>::
260 mutable_buffers_type::const_iterator
261 {
262 iter_type it_{};
263 buffers_adaptor const* b_ = nullptr;
264
265 public:
266 using value_type = net::mutable_buffer;
267 using pointer = value_type const*;
268 using reference = value_type;
269 using difference_type = std::ptrdiff_t;
270 using iterator_category =
271 std::bidirectional_iterator_tag;
272
273 const_iterator() = default;
274 const_iterator(const_iterator const& other) = default;
275 const_iterator& operator=(const_iterator const& other) = default;
276
277 bool
278 operator==(const_iterator const& other) const
279 {
280 return b_ == other.b_ && it_ == other.it_;
281 }
282
283 bool
284 operator!=(const_iterator const& other) const
285 {
286 return !(*this == other);
287 }
288
289 reference
290 operator*() const
291 {
292 value_type const b = *it_;
293 return value_type{b.data(),
294 it_ == std::prev(b_->end_) ?
295 b_->out_end_ : b.size()} +
296 (it_ == b_->out_ ? b_->out_pos_ : 0);
297 }
298
299 pointer
300 operator->() const = delete;
301
302 const_iterator&
303 operator++()
304 {
305 ++it_;
306 return *this;
307 }
308
309 const_iterator
310 operator++(int)
311 {
312 auto temp = *this;
313 ++(*this);
314 return temp;
315 }
316
317 const_iterator&
318 operator--()
319 {
320 --it_;
321 return *this;
322 }
323
324 const_iterator
325 operator--(int)
326 {
327 auto temp = *this;
328 --(*this);
329 return temp;
330 }
331
332 private:
333 friend class mutable_buffers_type;
334
335 const_iterator(buffers_adaptor const& b,
336 iter_type iter)
337 : it_(iter)
338 , b_(&b)
339 {
340 }
341 };
342
343 template<class MutableBufferSequence>
344 auto
345 buffers_adaptor<MutableBufferSequence>::
346 mutable_buffers_type::
347 begin() const ->
348 const_iterator
349 {
350 return const_iterator{*b_, b_->out_};
351 }
352
353 template<class MutableBufferSequence>
354 auto
355 buffers_adaptor<MutableBufferSequence>::
356 mutable_buffers_type::
357 end() const ->
358 const_iterator
359 {
360 return const_iterator{*b_, b_->end_};
361 }
362
363 //------------------------------------------------------------------------------
364
365 template<class MutableBufferSequence>
366 auto
367 buffers_adaptor<MutableBufferSequence>::
368 end_impl() const ->
369 iter_type
370 {
371 return out_ == end_ ? end_ : std::next(out_);
372 }
373
374 template<class MutableBufferSequence>
375 buffers_adaptor<MutableBufferSequence>::
376 buffers_adaptor(
377 buffers_adaptor const& other,
378 std::size_t nbegin,
379 std::size_t nout,
380 std::size_t nend)
381 : bs_(other.bs_)
382 , begin_(std::next(bs_.begin(), nbegin))
383 , out_(std::next(bs_.begin(), nout))
384 , end_(std::next(bs_.begin(), nend))
385 , max_size_(other.max_size_)
386 , in_pos_(other.in_pos_)
387 , in_size_(other.in_size_)
388 , out_pos_(other.out_pos_)
389 , out_end_(other.out_end_)
390 {
391 }
392
393 template<class MutableBufferSequence>
394 buffers_adaptor<MutableBufferSequence>::
395 buffers_adaptor(MutableBufferSequence const& bs)
396 : bs_(bs)
397 , begin_(net::buffer_sequence_begin(bs_))
398 , out_ (net::buffer_sequence_begin(bs_))
399 , end_ (net::buffer_sequence_begin(bs_))
400 , max_size_(
401 [&bs]
402 {
403 return buffer_bytes(bs);
404 }())
405 {
406 }
407
408 template<class MutableBufferSequence>
409 template<class... Args>
410 buffers_adaptor<MutableBufferSequence>::
411 buffers_adaptor(
412 boost::in_place_init_t, Args&&... args)
413 : bs_{std::forward<Args>(args)...}
414 , begin_(net::buffer_sequence_begin(bs_))
415 , out_ (net::buffer_sequence_begin(bs_))
416 , end_ (net::buffer_sequence_begin(bs_))
417 , max_size_(
418 [&]
419 {
420 return buffer_bytes(bs_);
421 }())
422 {
423 }
424
425 template<class MutableBufferSequence>
426 buffers_adaptor<MutableBufferSequence>::
427 buffers_adaptor(buffers_adaptor const& other)
428 : buffers_adaptor(
429 other,
430 std::distance<iter_type>(
431 net::buffer_sequence_begin(other.bs_),
432 other.begin_),
433 std::distance<iter_type>(
434 net::buffer_sequence_begin(other.bs_),
435 other.out_),
436 std::distance<iter_type>(
437 net::buffer_sequence_begin(other.bs_),
438 other.end_))
439 {
440 }
441
442 template<class MutableBufferSequence>
443 auto
444 buffers_adaptor<MutableBufferSequence>::
445 operator=(buffers_adaptor const& other) ->
446 buffers_adaptor&
447 {
448 if(this == &other)
449 return *this;
450 auto const nbegin = std::distance<iter_type>(
451 net::buffer_sequence_begin(other.bs_),
452 other.begin_);
453 auto const nout = std::distance<iter_type>(
454 net::buffer_sequence_begin(other.bs_),
455 other.out_);
456 auto const nend = std::distance<iter_type>(
457 net::buffer_sequence_begin(other.bs_),
458 other.end_);
459 bs_ = other.bs_;
460 begin_ = std::next(
461 net::buffer_sequence_begin(bs_), nbegin);
462 out_ = std::next(
463 net::buffer_sequence_begin(bs_), nout);
464 end_ = std::next(
465 net::buffer_sequence_begin(bs_), nend);
466 max_size_ = other.max_size_;
467 in_pos_ = other.in_pos_;
468 in_size_ = other.in_size_;
469 out_pos_ = other.out_pos_;
470 out_end_ = other.out_end_;
471 return *this;
472 }
473
474 //
475
476 template<class MutableBufferSequence>
477 auto
478 buffers_adaptor<MutableBufferSequence>::
479 data() const noexcept ->
480 const_buffers_type
481 {
482 return const_buffers_type{*this};
483 }
484
485 template<class MutableBufferSequence>
486 auto
487 buffers_adaptor<MutableBufferSequence>::
488 data() noexcept ->
489 mutable_data_type
490 {
491 return mutable_data_type{*this};
492 }
493
494 template<class MutableBufferSequence>
495 auto
496 buffers_adaptor<MutableBufferSequence>::
497 prepare(std::size_t n) ->
498 mutable_buffers_type
499 {
500 end_ = out_;
501 if(end_ != net::buffer_sequence_end(bs_))
502 {
503 auto size = buffer_bytes(*end_) - out_pos_;
504 if(n > size)
505 {
506 n -= size;
507 while(++end_ !=
508 net::buffer_sequence_end(bs_))
509 {
510 size = buffer_bytes(*end_);
511 if(n < size)
512 {
513 out_end_ = n;
514 n = 0;
515 ++end_;
516 break;
517 }
518 n -= size;
519 out_end_ = size;
520 }
521 }
522 else
523 {
524 ++end_;
525 out_end_ = out_pos_ + n;
526 n = 0;
527 }
528 }
529 if(n > 0)
530 BOOST_THROW_EXCEPTION(std::length_error{
531 "buffers_adaptor too long"});
532 return mutable_buffers_type{*this};
533 }
534
535 template<class MutableBufferSequence>
536 void
537 buffers_adaptor<MutableBufferSequence>::
538 commit(std::size_t n) noexcept
539 {
540 if(out_ == end_)
541 return;
542 auto const last = std::prev(end_);
543 while(out_ != last)
544 {
545 auto const avail =
546 buffer_bytes(*out_) - out_pos_;
547 if(n < avail)
548 {
549 out_pos_ += n;
550 in_size_ += n;
551 return;
552 }
553 ++out_;
554 n -= avail;
555 out_pos_ = 0;
556 in_size_ += avail;
557 }
558
559 n = std::min<std::size_t>(
560 n, out_end_ - out_pos_);
561 out_pos_ += n;
562 in_size_ += n;
563 if(out_pos_ == buffer_bytes(*out_))
564 {
565 ++out_;
566 out_pos_ = 0;
567 out_end_ = 0;
568 }
569 }
570
571 template<class MutableBufferSequence>
572 void
573 buffers_adaptor<MutableBufferSequence>::
574 consume(std::size_t n) noexcept
575 {
576 while(begin_ != out_)
577 {
578 auto const avail =
579 buffer_bytes(*begin_) - in_pos_;
580 if(n < avail)
581 {
582 in_size_ -= n;
583 in_pos_ += n;
584 return;
585 }
586 n -= avail;
587 in_size_ -= avail;
588 in_pos_ = 0;
589 ++begin_;
590 }
591 auto const avail = out_pos_ - in_pos_;
592 if(n < avail)
593 {
594 in_size_ -= n;
595 in_pos_ += n;
596 }
597 else
598 {
599 in_size_ -= avail;
600 in_pos_ = out_pos_;
601 }
602 }
603
604 } // beast
605 } // boost
606
607 #endif