2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
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)
7 // Official repository: https://github.com/boostorg/beast
10 #ifndef BOOST_BEAST_IMPL_BUFFERS_ADAPTOR_HPP
11 #define BOOST_BEAST_IMPL_BUFFERS_ADAPTOR_HPP
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>
21 #include <type_traits>
27 //------------------------------------------------------------------------------
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
35 template<class MutableBufferSequence>
36 template<bool isMutable>
37 class buffers_adaptor<MutableBufferSequence>::
40 buffers_adaptor const* b_;
43 using value_type = typename
44 std::conditional<isMutable,
46 net::const_buffer>::type;
50 readable_bytes() = delete;
52 #if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
54 readable_bytes const& other)
59 readable_bytes& operator=(
60 readable_bytes const& other)
67 readable_bytes const&) = default;
68 readable_bytes& operator=(
69 readable_bytes const&) = default;
72 template<bool isMutable_ = isMutable, class =
73 typename std::enable_if<! isMutable_>::type>
75 readable_bytes<true> const& other) noexcept
80 template<bool isMutable_ = isMutable, class =
81 typename std::enable_if<! isMutable_>::type>
82 readable_bytes& operator=(
83 readable_bytes<true> const& other) noexcept
96 friend class buffers_adaptor;
98 readable_bytes(buffers_adaptor const& b)
104 #if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
105 # pragma warning (pop)
108 //------------------------------------------------------------------------------
110 template<class MutableBufferSequence>
111 template<bool isMutable>
112 class buffers_adaptor<MutableBufferSequence>::
113 readable_bytes<isMutable>::
117 buffers_adaptor const* b_ = nullptr;
120 using value_type = typename
121 std::conditional<isMutable,
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;
130 const_iterator() = default;
131 const_iterator(const_iterator const& other) = default;
132 const_iterator& operator=(const_iterator const& other) = default;
135 operator==(const_iterator const& other) const
137 return b_ == other.b_ && it_ == other.it_;
141 operator!=(const_iterator const& other) const
143 return !(*this == other);
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);
157 operator->() const = delete;
190 friend class readable_bytes;
193 buffers_adaptor const& b,
201 template<class MutableBufferSequence>
202 template<bool isMutable>
204 buffers_adaptor<MutableBufferSequence>::
205 readable_bytes<isMutable>::
209 return const_iterator{*b_, b_->begin_};
212 template<class MutableBufferSequence>
213 template<bool isMutable>
215 buffers_adaptor<MutableBufferSequence>::
216 readable_bytes<isMutable>::
217 readable_bytes::end() const ->
220 return const_iterator{*b_, b_->end_impl()};
223 //------------------------------------------------------------------------------
225 template<class MutableBufferSequence>
226 class buffers_adaptor<MutableBufferSequence>::
229 buffers_adaptor const* b_;
232 using value_type = net::mutable_buffer;
234 class const_iterator;
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;
249 friend class buffers_adaptor;
251 mutable_buffers_type(
252 buffers_adaptor const& b)
258 template<class MutableBufferSequence>
259 class buffers_adaptor<MutableBufferSequence>::
260 mutable_buffers_type::const_iterator
263 buffers_adaptor const* b_ = nullptr;
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;
273 const_iterator() = default;
274 const_iterator(const_iterator const& other) = default;
275 const_iterator& operator=(const_iterator const& other) = default;
278 operator==(const_iterator const& other) const
280 return b_ == other.b_ && it_ == other.it_;
284 operator!=(const_iterator const& other) const
286 return !(*this == other);
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);
300 operator->() const = delete;
333 friend class mutable_buffers_type;
335 const_iterator(buffers_adaptor const& b,
343 template<class MutableBufferSequence>
345 buffers_adaptor<MutableBufferSequence>::
346 mutable_buffers_type::
350 return const_iterator{*b_, b_->out_};
353 template<class MutableBufferSequence>
355 buffers_adaptor<MutableBufferSequence>::
356 mutable_buffers_type::
360 return const_iterator{*b_, b_->end_};
363 //------------------------------------------------------------------------------
365 template<class MutableBufferSequence>
367 buffers_adaptor<MutableBufferSequence>::
371 return out_ == end_ ? end_ : std::next(out_);
374 template<class MutableBufferSequence>
375 buffers_adaptor<MutableBufferSequence>::
377 buffers_adaptor const& other,
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_)
393 template<class MutableBufferSequence>
394 buffers_adaptor<MutableBufferSequence>::
395 buffers_adaptor(MutableBufferSequence const& bs)
397 , begin_(net::buffer_sequence_begin(bs_))
398 , out_ (net::buffer_sequence_begin(bs_))
399 , end_ (net::buffer_sequence_begin(bs_))
403 return buffer_bytes(bs);
408 template<class MutableBufferSequence>
409 template<class... Args>
410 buffers_adaptor<MutableBufferSequence>::
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_))
420 return buffer_bytes(bs_);
425 template<class MutableBufferSequence>
426 buffers_adaptor<MutableBufferSequence>::
427 buffers_adaptor(buffers_adaptor const& other)
430 std::distance<iter_type>(
431 net::buffer_sequence_begin(other.bs_),
433 std::distance<iter_type>(
434 net::buffer_sequence_begin(other.bs_),
436 std::distance<iter_type>(
437 net::buffer_sequence_begin(other.bs_),
442 template<class MutableBufferSequence>
444 buffers_adaptor<MutableBufferSequence>::
445 operator=(buffers_adaptor const& other) ->
450 auto const nbegin = std::distance<iter_type>(
451 net::buffer_sequence_begin(other.bs_),
453 auto const nout = std::distance<iter_type>(
454 net::buffer_sequence_begin(other.bs_),
456 auto const nend = std::distance<iter_type>(
457 net::buffer_sequence_begin(other.bs_),
461 net::buffer_sequence_begin(bs_), nbegin);
463 net::buffer_sequence_begin(bs_), nout);
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_;
476 template<class MutableBufferSequence>
478 buffers_adaptor<MutableBufferSequence>::
479 data() const noexcept ->
482 return const_buffers_type{*this};
485 template<class MutableBufferSequence>
487 buffers_adaptor<MutableBufferSequence>::
491 return mutable_data_type{*this};
494 template<class MutableBufferSequence>
496 buffers_adaptor<MutableBufferSequence>::
497 prepare(std::size_t n) ->
501 if(end_ != net::buffer_sequence_end(bs_))
503 auto size = buffer_bytes(*end_) - out_pos_;
508 net::buffer_sequence_end(bs_))
510 size = buffer_bytes(*end_);
525 out_end_ = out_pos_ + n;
530 BOOST_THROW_EXCEPTION(std::length_error{
531 "buffers_adaptor too long"});
532 return mutable_buffers_type{*this};
535 template<class MutableBufferSequence>
537 buffers_adaptor<MutableBufferSequence>::
538 commit(std::size_t n) noexcept
542 auto const last = std::prev(end_);
546 buffer_bytes(*out_) - out_pos_;
559 n = std::min<std::size_t>(
560 n, out_end_ - out_pos_);
563 if(out_pos_ == buffer_bytes(*out_))
571 template<class MutableBufferSequence>
573 buffers_adaptor<MutableBufferSequence>::
574 consume(std::size_t n) noexcept
576 while(begin_ != out_)
579 buffer_bytes(*begin_) - in_pos_;
591 auto const avail = out_pos_ - in_pos_;