]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/beast/core/impl/buffers_adaptor.hpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / boost / boost / beast / core / impl / buffers_adaptor.hpp
CommitLineData
92f5a8d4
TL
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>
f67539c2 14#include <boost/beast/core/buffers_adaptor.hpp>
92f5a8d4
TL
15#include <boost/asio/buffer.hpp>
16#include <boost/config/workaround.hpp>
17#include <boost/throw_exception.hpp>
18#include <algorithm>
19#include <cstring>
20#include <iterator>
21#include <stdexcept>
22#include <type_traits>
23#include <utility>
24
25namespace boost {
26namespace beast {
27
28//------------------------------------------------------------------------------
29
30#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
31# pragma warning (push)
32# pragma warning (disable: 4521) // multiple copy constructors specified
33# pragma warning (disable: 4522) // multiple assignment operators specified
34#endif
35
36template<class MutableBufferSequence>
37template<bool isMutable>
f67539c2 38class buffers_adaptor<MutableBufferSequence>::subrange
92f5a8d4 39{
92f5a8d4 40public:
f67539c2
TL
41 using value_type = typename std::conditional<
42 isMutable,
43 net::mutable_buffer,
44 net::const_buffer>::type;
92f5a8d4 45
f67539c2 46 struct iterator;
92f5a8d4 47
f67539c2
TL
48 // construct from two iterators plus optionally subrange definition
49 subrange(
50 iter_type first, // iterator to first buffer in storage
51 iter_type last, // iterator to last buffer in storage
52 std::size_t pos = 0, // the offset in bytes from the beginning of the storage
53 std::size_t n = // the total length of the subrange
54 (std::numeric_limits<std::size_t>::max)());
92f5a8d4
TL
55
56#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
f67539c2
TL
57 subrange(
58 subrange const& other)
59 : first_(other.first_)
60 , last_(other.last_)
61 , first_offset_(other.first_offset_)
62 , last_size_(other.last_size_)
92f5a8d4
TL
63 {
64 }
65
f67539c2
TL
66 subrange& operator=(
67 subrange const& other)
92f5a8d4 68 {
f67539c2
TL
69 first_ = other.first_;
70 last_ = other.last_;
71 first_offset_ = other.first_offset_;
72 last_size_ = other.last_size_;
92f5a8d4
TL
73 return *this;
74 }
75#else
f67539c2
TL
76 subrange(
77 subrange const&) = default;
78 subrange& operator=(
79 subrange const&) = default;
92f5a8d4
TL
80#endif
81
f67539c2
TL
82 // allow conversion from mutable to const
83 template<bool isMutable_ = isMutable, typename
84 std::enable_if<!isMutable_>::type * = nullptr>
85 subrange(subrange<true> const &other)
86 : first_(other.first_)
87 , last_(other.last_)
88 , first_offset_(other.first_offset_)
89 , last_size_(other.last_size_)
92f5a8d4
TL
90 {
91 }
92
f67539c2 93 iterator
92f5a8d4
TL
94 begin() const;
95
f67539c2 96 iterator
92f5a8d4
TL
97 end() const;
98
99private:
92f5a8d4 100
f67539c2
TL
101 friend subrange<!isMutable>;
102
103 void
104 adjust(
105 std::size_t pos,
106 std::size_t n);
107
108private:
109 // points to the first buffer in the sequence
110 iter_type first_;
111
112 // Points to one past the end of the underlying buffer sequence
113 iter_type last_;
114
115 // The initial offset into the first buffer
116 std::size_t first_offset_;
117
118 // how many bytes in the penultimate buffer are used (if any)
119 std::size_t last_size_;
92f5a8d4
TL
120};
121
122#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
123# pragma warning (pop)
124#endif
125
126//------------------------------------------------------------------------------
127
128template<class MutableBufferSequence>
129template<bool isMutable>
f67539c2
TL
130struct buffers_adaptor<MutableBufferSequence>::
131 subrange<isMutable>::
132 iterator
92f5a8d4 133{
f67539c2 134 using iterator_category = std::bidirectional_iterator_tag;
92f5a8d4 135 using value_type = typename
f67539c2
TL
136 buffers_adaptor<MutableBufferSequence>::
137 template subrange<isMutable>::
138 value_type;
139 using reference = value_type&;
140 using pointer = value_type*;
92f5a8d4 141 using difference_type = std::ptrdiff_t;
92f5a8d4 142
f67539c2
TL
143 iterator(
144 subrange<isMutable> const *parent,
145 iter_type it);
92f5a8d4 146
f67539c2 147 iterator();
92f5a8d4 148
f67539c2
TL
149 value_type
150 operator*() const;
92f5a8d4
TL
151
152 pointer
153 operator->() const = delete;
154
f67539c2
TL
155 iterator &
156 operator++();
92f5a8d4 157
f67539c2
TL
158 iterator
159 operator++(int);
92f5a8d4 160
f67539c2
TL
161 iterator &
162 operator--();
92f5a8d4 163
f67539c2
TL
164 iterator
165 operator--(int);
92f5a8d4
TL
166
167 bool
f67539c2 168 operator==(iterator const &b) const;
92f5a8d4
TL
169
170 bool
f67539c2 171 operator!=(iterator const &b) const;
92f5a8d4
TL
172
173private:
92f5a8d4 174
f67539c2
TL
175 subrange<isMutable> const *parent_;
176 iter_type it_;
92f5a8d4
TL
177};
178
92f5a8d4
TL
179//------------------------------------------------------------------------------
180
181template<class MutableBufferSequence>
182auto
183buffers_adaptor<MutableBufferSequence>::
184end_impl() const ->
185 iter_type
186{
187 return out_ == end_ ? end_ : std::next(out_);
188}
189
190template<class MutableBufferSequence>
191buffers_adaptor<MutableBufferSequence>::
192buffers_adaptor(
193 buffers_adaptor const& other,
194 std::size_t nbegin,
195 std::size_t nout,
196 std::size_t nend)
197 : bs_(other.bs_)
198 , begin_(std::next(bs_.begin(), nbegin))
199 , out_(std::next(bs_.begin(), nout))
200 , end_(std::next(bs_.begin(), nend))
201 , max_size_(other.max_size_)
202 , in_pos_(other.in_pos_)
203 , in_size_(other.in_size_)
204 , out_pos_(other.out_pos_)
205 , out_end_(other.out_end_)
206{
207}
208
209template<class MutableBufferSequence>
210buffers_adaptor<MutableBufferSequence>::
211buffers_adaptor(MutableBufferSequence const& bs)
212 : bs_(bs)
213 , begin_(net::buffer_sequence_begin(bs_))
214 , out_ (net::buffer_sequence_begin(bs_))
215 , end_ (net::buffer_sequence_begin(bs_))
216 , max_size_(
217 [&bs]
218 {
219 return buffer_bytes(bs);
220 }())
221{
222}
223
224template<class MutableBufferSequence>
225template<class... Args>
226buffers_adaptor<MutableBufferSequence>::
227buffers_adaptor(
228 boost::in_place_init_t, Args&&... args)
229 : bs_{std::forward<Args>(args)...}
230 , begin_(net::buffer_sequence_begin(bs_))
231 , out_ (net::buffer_sequence_begin(bs_))
232 , end_ (net::buffer_sequence_begin(bs_))
233 , max_size_(
234 [&]
235 {
236 return buffer_bytes(bs_);
237 }())
238{
239}
240
241template<class MutableBufferSequence>
242buffers_adaptor<MutableBufferSequence>::
243buffers_adaptor(buffers_adaptor const& other)
244 : buffers_adaptor(
245 other,
246 std::distance<iter_type>(
247 net::buffer_sequence_begin(other.bs_),
248 other.begin_),
249 std::distance<iter_type>(
250 net::buffer_sequence_begin(other.bs_),
251 other.out_),
252 std::distance<iter_type>(
253 net::buffer_sequence_begin(other.bs_),
254 other.end_))
255{
256}
257
258template<class MutableBufferSequence>
259auto
260buffers_adaptor<MutableBufferSequence>::
261operator=(buffers_adaptor const& other) ->
262 buffers_adaptor&
263{
264 if(this == &other)
265 return *this;
266 auto const nbegin = std::distance<iter_type>(
267 net::buffer_sequence_begin(other.bs_),
268 other.begin_);
269 auto const nout = std::distance<iter_type>(
270 net::buffer_sequence_begin(other.bs_),
271 other.out_);
272 auto const nend = std::distance<iter_type>(
273 net::buffer_sequence_begin(other.bs_),
274 other.end_);
275 bs_ = other.bs_;
276 begin_ = std::next(
277 net::buffer_sequence_begin(bs_), nbegin);
278 out_ = std::next(
279 net::buffer_sequence_begin(bs_), nout);
280 end_ = std::next(
281 net::buffer_sequence_begin(bs_), nend);
282 max_size_ = other.max_size_;
283 in_pos_ = other.in_pos_;
284 in_size_ = other.in_size_;
285 out_pos_ = other.out_pos_;
286 out_end_ = other.out_end_;
287 return *this;
288}
289
290//
291
292template<class MutableBufferSequence>
293auto
294buffers_adaptor<MutableBufferSequence>::
295data() const noexcept ->
296 const_buffers_type
297{
f67539c2
TL
298 return const_buffers_type(
299 begin_, end_,
300 in_pos_, in_size_);
92f5a8d4
TL
301}
302
303template<class MutableBufferSequence>
304auto
305buffers_adaptor<MutableBufferSequence>::
306data() noexcept ->
f67539c2 307 mutable_buffers_type
92f5a8d4 308{
f67539c2
TL
309 return mutable_buffers_type(
310 begin_, end_,
311 in_pos_, in_size_);
92f5a8d4
TL
312}
313
314template<class MutableBufferSequence>
315auto
316buffers_adaptor<MutableBufferSequence>::
317prepare(std::size_t n) ->
318 mutable_buffers_type
319{
f67539c2 320 auto prepared = n;
92f5a8d4
TL
321 end_ = out_;
322 if(end_ != net::buffer_sequence_end(bs_))
323 {
324 auto size = buffer_bytes(*end_) - out_pos_;
325 if(n > size)
326 {
327 n -= size;
328 while(++end_ !=
329 net::buffer_sequence_end(bs_))
330 {
331 size = buffer_bytes(*end_);
332 if(n < size)
333 {
334 out_end_ = n;
335 n = 0;
336 ++end_;
337 break;
338 }
339 n -= size;
340 out_end_ = size;
341 }
342 }
343 else
344 {
345 ++end_;
346 out_end_ = out_pos_ + n;
347 n = 0;
348 }
349 }
350 if(n > 0)
351 BOOST_THROW_EXCEPTION(std::length_error{
352 "buffers_adaptor too long"});
f67539c2 353 return mutable_buffers_type(out_, end_, out_pos_, prepared);
92f5a8d4
TL
354}
355
356template<class MutableBufferSequence>
357void
358buffers_adaptor<MutableBufferSequence>::
359commit(std::size_t n) noexcept
360{
361 if(out_ == end_)
362 return;
363 auto const last = std::prev(end_);
364 while(out_ != last)
365 {
366 auto const avail =
367 buffer_bytes(*out_) - out_pos_;
368 if(n < avail)
369 {
370 out_pos_ += n;
371 in_size_ += n;
372 return;
373 }
374 ++out_;
375 n -= avail;
376 out_pos_ = 0;
377 in_size_ += avail;
378 }
379
380 n = std::min<std::size_t>(
381 n, out_end_ - out_pos_);
382 out_pos_ += n;
383 in_size_ += n;
384 if(out_pos_ == buffer_bytes(*out_))
385 {
386 ++out_;
387 out_pos_ = 0;
388 out_end_ = 0;
389 }
390}
391
392template<class MutableBufferSequence>
393void
394buffers_adaptor<MutableBufferSequence>::
395consume(std::size_t n) noexcept
396{
397 while(begin_ != out_)
398 {
399 auto const avail =
400 buffer_bytes(*begin_) - in_pos_;
401 if(n < avail)
402 {
403 in_size_ -= n;
404 in_pos_ += n;
405 return;
406 }
407 n -= avail;
408 in_size_ -= avail;
409 in_pos_ = 0;
410 ++begin_;
411 }
412 auto const avail = out_pos_ - in_pos_;
413 if(n < avail)
414 {
415 in_size_ -= n;
416 in_pos_ += n;
417 }
418 else
419 {
420 in_size_ -= avail;
421 in_pos_ = out_pos_;
422 }
423}
424
f67539c2
TL
425template<class MutableBufferSequence>
426auto
427buffers_adaptor<MutableBufferSequence>::
428 make_subrange(std::size_t pos, std::size_t n) ->
429 subrange<true>
430{
431 return subrange<true>(
432 begin_, net::buffer_sequence_end(bs_),
433 in_pos_ + pos, n);
434}
435
436template<class MutableBufferSequence>
437auto
438buffers_adaptor<MutableBufferSequence>::
439 make_subrange(std::size_t pos, std::size_t n) const ->
440 subrange<false>
441{
442 return subrange<false>(
443 begin_, net::buffer_sequence_end(bs_),
444 in_pos_ + pos, n);
445}
446
447// -------------------------------------------------------------------------
448// subrange
449
450template<class MutableBufferSequence>
451template<bool isMutable>
452buffers_adaptor<MutableBufferSequence>::
453subrange<isMutable>::
454subrange(
455 iter_type first, // iterator to first buffer in storage
456 iter_type last, // iterator to last buffer in storage
457 std::size_t pos, // the offset in bytes from the beginning of the storage
458 std::size_t n) // the total length of the subrange
459 : first_(first)
460 , last_(last)
461 , first_offset_(0)
462 , last_size_((std::numeric_limits<std::size_t>::max)())
463{
464 adjust(pos, n);
465}
466
467template<class MutableBufferSequence>
468template<bool isMutable>
469void
470buffers_adaptor<MutableBufferSequence>::
471 subrange<isMutable>::
472adjust(
473 std::size_t pos,
474 std::size_t n)
475{
476 if (n == 0)
477 last_ = first_;
478
479 if (first_ == last_)
480 {
481 first_offset_ = 0;
482 last_size_ = 0;
483 return;
484 }
485
486 auto is_last = [this](iter_type iter) {
487 return std::next(iter) == last_;
488 };
489
490
491 pos += first_offset_;
492 while (pos)
493 {
494 auto adjust = (std::min)(pos, first_->size());
495 if (adjust >= first_->size())
496 {
497 ++first_;
498 first_offset_ = 0;
499 pos -= adjust;
500 }
501 else
502 {
503 first_offset_ = adjust;
504 pos = 0;
505 break;
506 }
507 }
508
509 auto current = first_;
510 auto max_elem = current->size() - first_offset_;
511 if (is_last(current))
512 {
513 // both first and last element
514 last_size_ = (std::min)(max_elem, n);
515 last_ = std::next(current);
516 return;
517 }
518 else if (max_elem >= n)
519 {
520 last_ = std::next(current);
521 last_size_ = n;
522 }
523 else
524 {
525 n -= max_elem;
526 ++current;
527 }
528
529 for (;;)
530 {
531 max_elem = current->size();
532 if (is_last(current))
533 {
534 last_size_ = (std::min)(n, last_size_);
535 return;
536 }
537 else if (max_elem < n)
538 {
539 n -= max_elem;
540 ++current;
541 }
542 else
543 {
544 last_size_ = n;
545 last_ = std::next(current);
546 return;
547 }
548 }
549}
550
551
552template<class MutableBufferSequence>
553template<bool isMutable>
554auto
555buffers_adaptor<MutableBufferSequence>::
556 subrange<isMutable>::
557begin() const ->
558iterator
559{
560 return iterator(this, first_);
561}
562
563template<class MutableBufferSequence>
564template<bool isMutable>
565auto
566buffers_adaptor<MutableBufferSequence>::
567 subrange<isMutable>::
568end() const ->
569iterator
570{
571 return iterator(this, last_);
572}
573
574// -------------------------------------------------------------------------
575// buffers_adaptor::subrange::iterator
576
577template<class MutableBufferSequence>
578template<bool isMutable>
579buffers_adaptor<MutableBufferSequence>::
580subrange<isMutable>::
581iterator::
582iterator()
583 : parent_(nullptr)
584 , it_()
585{
586}
587
588template<class MutableBufferSequence>
589template<bool isMutable>
590buffers_adaptor<MutableBufferSequence>::
591subrange<isMutable>::
592iterator::
593iterator(subrange<isMutable> const *parent,
594 iter_type it)
595 : parent_(parent)
596 , it_(it)
597{
598}
599
600template<class MutableBufferSequence>
601template<bool isMutable>
602auto
603buffers_adaptor<MutableBufferSequence>::
604 subrange<isMutable>::
605 iterator::
606operator*() const ->
607 value_type
608{
609 value_type result = *it_;
610
611 if (it_ == parent_->first_)
612 result += parent_->first_offset_;
613
614 if (std::next(it_) == parent_->last_)
615 {
616 result = value_type(
617 result.data(),
618 (std::min)(
619 parent_->last_size_,
620 result.size()));
621 }
622
623 return result;
624}
625
626template<class MutableBufferSequence>
627template<bool isMutable>
628auto
629buffers_adaptor<MutableBufferSequence>::
630 subrange<isMutable>::
631 iterator::
632operator++() ->
633 iterator &
634{
635 ++it_;
636 return *this;
637}
638
639template<class MutableBufferSequence>
640template<bool isMutable>
641auto
642buffers_adaptor<MutableBufferSequence>::
643 subrange<isMutable>::
644 iterator::
645operator++(int) ->
646 iterator
647{
648 auto result = *this;
649 ++it_;
650 return result;
651}
652
653template<class MutableBufferSequence>
654template<bool isMutable>
655auto
656buffers_adaptor<MutableBufferSequence>::
657 subrange<isMutable>::
658 iterator::
659operator--() ->
660 iterator &
661{
662 --it_;
663 return *this;
664}
665
666template<class MutableBufferSequence>
667template<bool isMutable>
668auto
669buffers_adaptor<MutableBufferSequence>::
670 subrange<isMutable>::
671 iterator::
672operator--(int) ->
673 iterator
674{
675 auto result = *this;
676 --it_;
677 return result;
678}
679
680template<class MutableBufferSequence>
681template<bool isMutable>
682auto
683buffers_adaptor<MutableBufferSequence>::
684 subrange<isMutable>::
685 iterator::
686operator==(iterator const &b) const ->
687 bool
688{
689 return it_ == b.it_;
690}
691
692template<class MutableBufferSequence>
693template<bool isMutable>
694auto
695buffers_adaptor<MutableBufferSequence>::
696 subrange<isMutable>::
697 iterator::
698operator!=(iterator const &b) const ->
699 bool
700{
701 return !(*this == b);
702}
703
92f5a8d4
TL
704} // beast
705} // boost
706
707#endif