]> git.proxmox.com Git - ceph.git/blob - 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
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
19 namespace beast {
20
21 template<class MutableBufferSequence>
22 class buffers_adapter<MutableBufferSequence>::
23 const_buffers_type
24 {
25 buffers_adapter const* ba_;
26
27 public:
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
44 private:
45 friend class buffers_adapter;
46
47 const_buffers_type(buffers_adapter const& ba)
48 : ba_(&ba)
49 {
50 }
51 };
52
53 template<class MutableBufferSequence>
54 class buffers_adapter<MutableBufferSequence>::
55 const_buffers_type::const_iterator
56 {
57 iter_type it_;
58 buffers_adapter const* ba_ = nullptr;
59
60 public:
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
131 private:
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
142 template<class MutableBufferSequence>
143 inline
144 auto
145 buffers_adapter<MutableBufferSequence>::const_buffers_type::begin() const ->
146 const_iterator
147 {
148 return const_iterator{*ba_, ba_->begin_};
149 }
150
151 template<class MutableBufferSequence>
152 inline
153 auto
154 buffers_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
163 template<class MutableBufferSequence>
164 class buffers_adapter<MutableBufferSequence>::
165 mutable_buffers_type
166 {
167 buffers_adapter const* ba_;
168
169 public:
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
186 private:
187 friend class buffers_adapter;
188
189 mutable_buffers_type(
190 buffers_adapter const& ba)
191 : ba_(&ba)
192 {
193 }
194 };
195
196 template<class MutableBufferSequence>
197 class buffers_adapter<MutableBufferSequence>::
198 mutable_buffers_type::const_iterator
199 {
200 iter_type it_;
201 buffers_adapter const* ba_ = nullptr;
202
203 public:
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
274 private:
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
285 template<class MutableBufferSequence>
286 inline
287 auto
288 buffers_adapter<MutableBufferSequence>::mutable_buffers_type::begin() const ->
289 const_iterator
290 {
291 return const_iterator{*ba_, ba_->out_};
292 }
293
294 template<class MutableBufferSequence>
295 inline
296 auto
297 buffers_adapter<MutableBufferSequence>::mutable_buffers_type::end() const ->
298 const_iterator
299 {
300 return const_iterator{*ba_, ba_->end_};
301 }
302
303 //------------------------------------------------------------------------------
304
305 template<class MutableBufferSequence>
306 buffers_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
315 template<class MutableBufferSequence>
316 buffers_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
325 template<class MutableBufferSequence>
326 auto
327 buffers_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
348 template<class MutableBufferSequence>
349 auto
350 buffers_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
371 template<class MutableBufferSequence>
372 buffers_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
382 template<class MutableBufferSequence>
383 auto
384 buffers_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
422 template<class MutableBufferSequence>
423 void
424 buffers_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
460 template<class MutableBufferSequence>
461 inline
462 auto
463 buffers_adapter<MutableBufferSequence>::data() const ->
464 const_buffers_type
465 {
466 return const_buffers_type{*this};
467 }
468
469 template<class MutableBufferSequence>
470 void
471 buffers_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