]> git.proxmox.com Git - ceph.git/blame - ceph/src/Beast/include/beast/core/impl/buffers_adapter.ipp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / Beast / include / beast / core / impl / buffers_adapter.ipp
CommitLineData
7c673cae
FG
1//
2// Copyright (c) 2013-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
8#ifndef BEAST_IMPL_BUFFERS_ADAPTER_IPP
9#define BEAST_IMPL_BUFFERS_ADAPTER_IPP
10
11#include <beast/core/detail/type_traits.hpp>
12#include <boost/asio/buffer.hpp>
13#include <algorithm>
14#include <cstring>
15#include <iterator>
16#include <stdexcept>
17#include <type_traits>
18
19namespace beast {
20
21template<class MutableBufferSequence>
22class buffers_adapter<MutableBufferSequence>::
23 const_buffers_type
24{
25 buffers_adapter const* ba_;
26
27public:
28 using value_type = boost::asio::const_buffer;
29
30 class const_iterator;
31
32 const_buffers_type() = delete;
33 const_buffers_type(
34 const_buffers_type const&) = default;
35 const_buffers_type& operator=(
36 const_buffers_type const&) = default;
37
38 const_iterator
39 begin() const;
40
41 const_iterator
42 end() const;
43
44private:
45 friend class buffers_adapter;
46
47 const_buffers_type(buffers_adapter const& ba)
48 : ba_(&ba)
49 {
50 }
51};
52
53template<class MutableBufferSequence>
54class buffers_adapter<MutableBufferSequence>::
55 const_buffers_type::const_iterator
56{
57 iter_type it_;
58 buffers_adapter const* ba_ = nullptr;
59
60public:
61 using value_type = boost::asio::const_buffer;
62 using pointer = value_type const*;
63 using reference = value_type;
64 using difference_type = std::ptrdiff_t;
65 using iterator_category =
66 std::bidirectional_iterator_tag;
67
68 const_iterator() = default;
69 const_iterator(const_iterator&& other) = default;
70 const_iterator(const_iterator const& other) = default;
71 const_iterator& operator=(const_iterator&& other) = default;
72 const_iterator& operator=(const_iterator const& other) = default;
73
74 bool
75 operator==(const_iterator const& other) const
76 {
77 return ba_ == other.ba_ &&
78 it_ == other.it_;
79 }
80
81 bool
82 operator!=(const_iterator const& other) const
83 {
84 return !(*this == other);
85 }
86
87 reference
88 operator*() const
89 {
90 using boost::asio::buffer_cast;
91 using boost::asio::buffer_size;
92 return value_type{buffer_cast<void const*>(*it_),
93 (ba_->out_ == ba_->bs_.end() ||
94 it_ != ba_->out_) ? buffer_size(*it_) : ba_->out_pos_} +
95 (it_ == ba_->begin_ ? ba_->in_pos_ : 0);
96 }
97
98 pointer
99 operator->() const = delete;
100
101 const_iterator&
102 operator++()
103 {
104 ++it_;
105 return *this;
106 }
107
108 const_iterator
109 operator++(int)
110 {
111 auto temp = *this;
112 ++(*this);
113 return temp;
114 }
115
116 const_iterator&
117 operator--()
118 {
119 --it_;
120 return *this;
121 }
122
123 const_iterator
124 operator--(int)
125 {
126 auto temp = *this;
127 --(*this);
128 return temp;
129 }
130
131private:
132 friend class const_buffers_type;
133
134 const_iterator(buffers_adapter const& ba,
135 iter_type iter)
136 : it_(iter)
137 , ba_(&ba)
138 {
139 }
140};
141
142template<class MutableBufferSequence>
143inline
144auto
145buffers_adapter<MutableBufferSequence>::const_buffers_type::begin() const ->
146 const_iterator
147{
148 return const_iterator{*ba_, ba_->begin_};
149}
150
151template<class MutableBufferSequence>
152inline
153auto
154buffers_adapter<MutableBufferSequence>::const_buffers_type::end() const ->
155 const_iterator
156{
157 return const_iterator{*ba_, ba_->out_ ==
158 ba_->end_ ? ba_->end_ : std::next(ba_->out_)};
159}
160
161//------------------------------------------------------------------------------
162
163template<class MutableBufferSequence>
164class buffers_adapter<MutableBufferSequence>::
165mutable_buffers_type
166{
167 buffers_adapter const* ba_;
168
169public:
170 using value_type = boost::asio::mutable_buffer;
171
172 class const_iterator;
173
174 mutable_buffers_type() = delete;
175 mutable_buffers_type(
176 mutable_buffers_type const&) = default;
177 mutable_buffers_type& operator=(
178 mutable_buffers_type const&) = default;
179
180 const_iterator
181 begin() const;
182
183 const_iterator
184 end() const;
185
186private:
187 friend class buffers_adapter;
188
189 mutable_buffers_type(
190 buffers_adapter const& ba)
191 : ba_(&ba)
192 {
193 }
194};
195
196template<class MutableBufferSequence>
197class buffers_adapter<MutableBufferSequence>::
198mutable_buffers_type::const_iterator
199{
200 iter_type it_;
201 buffers_adapter const* ba_ = nullptr;
202
203public:
204 using value_type = boost::asio::mutable_buffer;
205 using pointer = value_type const*;
206 using reference = value_type;
207 using difference_type = std::ptrdiff_t;
208 using iterator_category =
209 std::bidirectional_iterator_tag;
210
211 const_iterator() = default;
212 const_iterator(const_iterator&& other) = default;
213 const_iterator(const_iterator const& other) = default;
214 const_iterator& operator=(const_iterator&& other) = default;
215 const_iterator& operator=(const_iterator const& other) = default;
216
217 bool
218 operator==(const_iterator const& other) const
219 {
220 return ba_ == other.ba_ &&
221 it_ == other.it_;
222 }
223
224 bool
225 operator!=(const_iterator const& other) const
226 {
227 return !(*this == other);
228 }
229
230 reference
231 operator*() const
232 {
233 using boost::asio::buffer_cast;
234 using boost::asio::buffer_size;
235 return value_type{buffer_cast<void*>(*it_),
236 it_ == std::prev(ba_->end_) ?
237 ba_->out_end_ : buffer_size(*it_)} +
238 (it_ == ba_->out_ ? ba_->out_pos_ : 0);
239 }
240
241 pointer
242 operator->() const = delete;
243
244 const_iterator&
245 operator++()
246 {
247 ++it_;
248 return *this;
249 }
250
251 const_iterator
252 operator++(int)
253 {
254 auto temp = *this;
255 ++(*this);
256 return temp;
257 }
258
259 const_iterator&
260 operator--()
261 {
262 --it_;
263 return *this;
264 }
265
266 const_iterator
267 operator--(int)
268 {
269 auto temp = *this;
270 --(*this);
271 return temp;
272 }
273
274private:
275 friend class mutable_buffers_type;
276
277 const_iterator(buffers_adapter const& ba,
278 iter_type iter)
279 : it_(iter)
280 , ba_(&ba)
281 {
282 }
283};
284
285template<class MutableBufferSequence>
286inline
287auto
288buffers_adapter<MutableBufferSequence>::mutable_buffers_type::begin() const ->
289 const_iterator
290{
291 return const_iterator{*ba_, ba_->out_};
292}
293
294template<class MutableBufferSequence>
295inline
296auto
297buffers_adapter<MutableBufferSequence>::mutable_buffers_type::end() const ->
298 const_iterator
299{
300 return const_iterator{*ba_, ba_->end_};
301}
302
303//------------------------------------------------------------------------------
304
305template<class MutableBufferSequence>
306buffers_adapter<MutableBufferSequence>::buffers_adapter(
307 buffers_adapter&& other)
308 : buffers_adapter(std::move(other),
309 std::distance<iter_type>(other.bs_.begin(), other.begin_),
310 std::distance<iter_type>(other.bs_.begin(), other.out_),
311 std::distance<iter_type>(other.bs_.begin(), other.end_))
312{
313}
314
315template<class MutableBufferSequence>
316buffers_adapter<MutableBufferSequence>::buffers_adapter(
317 buffers_adapter const& other)
318 : buffers_adapter(other,
319 std::distance<iter_type>(other.bs_.begin(), other.begin_),
320 std::distance<iter_type>(other.bs_.begin(), other.out_),
321 std::distance<iter_type>(other.bs_.begin(), other.end_))
322{
323}
324
325template<class MutableBufferSequence>
326auto
327buffers_adapter<MutableBufferSequence>::operator=(
328 buffers_adapter&& other) -> buffers_adapter&
329{
330 auto const nbegin = std::distance<iter_type>(
331 other.bs_.begin(), other.begin_);
332 auto const nout = std::distance<iter_type>(
333 other.bs_.begin(), other.out_);
334 auto const nend = std::distance<iter_type>(
335 other.bs_.begin(), other.end_);
336 bs_ = std::move(other.bs_);
337 begin_ = std::next(bs_.begin(), nbegin);
338 out_ = std::next(bs_.begin(), nout);
339 end_ = std::next(bs_.begin(), nend);
340 max_size_ = other.max_size_;
341 in_pos_ = other.in_pos_;
342 in_size_ = other.in_size_;
343 out_pos_ = other.out_pos_;
344 out_end_ = other.out_end_;
345 return *this;
346}
347
348template<class MutableBufferSequence>
349auto
350buffers_adapter<MutableBufferSequence>::operator=(
351 buffers_adapter const& other) -> buffers_adapter&
352{
353 auto const nbegin = std::distance<iter_type>(
354 other.bs_.begin(), other.begin_);
355 auto const nout = std::distance<iter_type>(
356 other.bs_.begin(), other.out_);
357 auto const nend = std::distance<iter_type>(
358 other.bs_.begin(), other.end_);
359 bs_ = other.bs_;
360 begin_ = std::next(bs_.begin(), nbegin);
361 out_ = std::next(bs_.begin(), nout);
362 end_ = std::next(bs_.begin(), nend);
363 max_size_ = other.max_size_;
364 in_pos_ = other.in_pos_;
365 in_size_ = other.in_size_;
366 out_pos_ = other.out_pos_;
367 out_end_ = other.out_end_;
368 return *this;
369}
370
371template<class MutableBufferSequence>
372buffers_adapter<MutableBufferSequence>::buffers_adapter(
373 MutableBufferSequence const& bs)
374 : bs_(bs)
375 , begin_(bs_.begin())
376 , out_(bs_.begin())
377 , end_(bs_.begin())
378 , max_size_(boost::asio::buffer_size(bs_))
379{
380}
381
382template<class MutableBufferSequence>
383auto
384buffers_adapter<MutableBufferSequence>::prepare(std::size_t n) ->
385 mutable_buffers_type
386{
387 using boost::asio::buffer_size;
388 end_ = out_;
389 if(end_ != bs_.end())
390 {
391 auto size = buffer_size(*end_) - out_pos_;
392 if(n > size)
393 {
394 n -= size;
395 while(++end_ != bs_.end())
396 {
397 size = buffer_size(*end_);
398 if(n < size)
399 {
400 out_end_ = n;
401 n = 0;
402 ++end_;
403 break;
404 }
405 n -= size;
406 out_end_ = size;
407 }
408 }
409 else
410 {
411 ++end_;
412 out_end_ = out_pos_ + n;
413 n = 0;
414 }
415 }
416 if(n > 0)
417 throw detail::make_exception<std::length_error>(
418 "no space", __FILE__, __LINE__);
419 return mutable_buffers_type{*this};
420}
421
422template<class MutableBufferSequence>
423void
424buffers_adapter<MutableBufferSequence>::commit(std::size_t n)
425{
426 using boost::asio::buffer_size;
427 if(out_ == end_)
428 return;
429 auto const last = std::prev(end_);
430 while(out_ != last)
431 {
432 auto const avail =
433 buffer_size(*out_) - out_pos_;
434 if(n < avail)
435 {
436 out_pos_ += n;
437 in_size_ += n;
438 max_size_ -= n;
439 return;
440 }
441 ++out_;
442 n -= avail;
443 out_pos_ = 0;
444 in_size_ += avail;
445 max_size_ -= avail;
446 }
447
448 n = (std::min)(n, out_end_ - out_pos_);
449 out_pos_ += n;
450 in_size_ += n;
451 max_size_ -= n;
452 if(out_pos_ == buffer_size(*out_))
453 {
454 ++out_;
455 out_pos_ = 0;
456 out_end_ = 0;
457 }
458}
459
460template<class MutableBufferSequence>
461inline
462auto
463buffers_adapter<MutableBufferSequence>::data() const ->
464 const_buffers_type
465{
466 return const_buffers_type{*this};
467}
468
469template<class MutableBufferSequence>
470void
471buffers_adapter<MutableBufferSequence>::consume(std::size_t n)
472{
473 using boost::asio::buffer_size;
474 while(begin_ != out_)
475 {
476 auto const avail =
477 buffer_size(*begin_) - in_pos_;
478 if(n < avail)
479 {
480 in_size_ -= n;
481 in_pos_ += n;
482 return;
483 }
484 n -= avail;
485 in_size_ -= avail;
486 in_pos_ = 0;
487 ++begin_;
488 }
489 auto const avail = out_pos_ - in_pos_;
490 if(n < avail)
491 {
492 in_size_ -= n;
493 in_pos_ += n;
494 }
495 else
496 {
497 in_size_ -= avail;
498 in_pos_ = out_pos_;
499 }
500}
501
502} // beast
503
504#endif