2 // Copyright (c) 2016-2017 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_ADAPTER_IPP
11 #define BOOST_BEAST_IMPL_BUFFERS_ADAPTER_IPP
13 #include <boost/beast/core/detail/type_traits.hpp>
14 #include <boost/asio/buffer.hpp>
15 #include <boost/throw_exception.hpp>
24 template<class MutableBufferSequence>
25 class buffers_adapter<MutableBufferSequence>::
28 buffers_adapter const* ba_;
31 using value_type = boost::asio::mutable_buffer;
35 const_buffers_type() = delete;
37 const_buffers_type const&) = default;
38 const_buffers_type& operator=(
39 const_buffers_type const&) = default;
48 friend class buffers_adapter;
50 const_buffers_type(buffers_adapter const& ba)
56 template<class MutableBufferSequence>
57 class buffers_adapter<MutableBufferSequence>::
58 const_buffers_type::const_iterator
61 buffers_adapter const* ba_ = nullptr;
64 using value_type = boost::asio::const_buffer;
65 using pointer = value_type const*;
66 using reference = value_type;
67 using difference_type = std::ptrdiff_t;
68 using iterator_category =
69 std::bidirectional_iterator_tag;
71 const_iterator() = default;
72 const_iterator(const_iterator&& other) = default;
73 const_iterator(const_iterator const& other) = default;
74 const_iterator& operator=(const_iterator&& other) = default;
75 const_iterator& operator=(const_iterator const& other) = default;
78 operator==(const_iterator const& other) const
80 return ba_ == other.ba_ &&
85 operator!=(const_iterator const& other) const
87 return !(*this == other);
93 value_type const b = *it_;
94 return value_type{b.data(),
95 (ba_->out_ == boost::asio::buffer_sequence_end(ba_->bs_) ||
96 it_ != ba_->out_) ? b.size() : ba_->out_pos_} +
97 (it_ == ba_->begin_ ? ba_->in_pos_ : 0);
101 operator->() const = delete;
134 friend class const_buffers_type;
136 const_iterator(buffers_adapter const& ba,
144 template<class MutableBufferSequence>
147 buffers_adapter<MutableBufferSequence>::const_buffers_type::begin() const ->
150 return const_iterator{*ba_, ba_->begin_};
153 template<class MutableBufferSequence>
156 buffers_adapter<MutableBufferSequence>::const_buffers_type::end() const ->
159 return const_iterator{*ba_, ba_->out_ ==
160 ba_->end_ ? ba_->end_ : std::next(ba_->out_)};
163 //------------------------------------------------------------------------------
165 template<class MutableBufferSequence>
166 class buffers_adapter<MutableBufferSequence>::
169 buffers_adapter const* ba_;
172 using value_type = boost::asio::mutable_buffer;
174 class const_iterator;
176 mutable_buffers_type() = delete;
177 mutable_buffers_type(
178 mutable_buffers_type const&) = default;
179 mutable_buffers_type& operator=(
180 mutable_buffers_type const&) = default;
189 friend class buffers_adapter;
191 mutable_buffers_type(
192 buffers_adapter const& ba)
198 template<class MutableBufferSequence>
199 class buffers_adapter<MutableBufferSequence>::
200 mutable_buffers_type::const_iterator
203 buffers_adapter const* ba_ = nullptr;
206 using value_type = boost::asio::mutable_buffer;
207 using pointer = value_type const*;
208 using reference = value_type;
209 using difference_type = std::ptrdiff_t;
210 using iterator_category =
211 std::bidirectional_iterator_tag;
213 const_iterator() = default;
214 const_iterator(const_iterator&& other) = default;
215 const_iterator(const_iterator const& other) = default;
216 const_iterator& operator=(const_iterator&& other) = default;
217 const_iterator& operator=(const_iterator const& other) = default;
220 operator==(const_iterator const& other) const
222 return ba_ == other.ba_ &&
227 operator!=(const_iterator const& other) const
229 return !(*this == other);
235 value_type const b = *it_;
236 return value_type{b.data(),
237 it_ == std::prev(ba_->end_) ?
238 ba_->out_end_ : b.size()} +
239 (it_ == ba_->out_ ? ba_->out_pos_ : 0);
243 operator->() const = delete;
276 friend class mutable_buffers_type;
278 const_iterator(buffers_adapter const& ba,
286 template<class MutableBufferSequence>
289 buffers_adapter<MutableBufferSequence>::
290 mutable_buffers_type::
294 return const_iterator{*ba_, ba_->out_};
297 template<class MutableBufferSequence>
300 buffers_adapter<MutableBufferSequence>::
301 mutable_buffers_type::
305 return const_iterator{*ba_, ba_->end_};
308 //------------------------------------------------------------------------------
310 template<class MutableBufferSequence>
311 buffers_adapter<MutableBufferSequence>::buffers_adapter(
312 buffers_adapter&& other)
313 : buffers_adapter(std::move(other),
314 std::distance<iter_type>(boost::asio::buffer_sequence_begin(other.bs_), other.begin_),
315 std::distance<iter_type>(boost::asio::buffer_sequence_begin(other.bs_), other.out_),
316 std::distance<iter_type>(boost::asio::buffer_sequence_begin(other.bs_), other.end_))
320 template<class MutableBufferSequence>
321 buffers_adapter<MutableBufferSequence>::buffers_adapter(
322 buffers_adapter const& other)
323 : buffers_adapter(other,
324 std::distance<iter_type>(boost::asio::buffer_sequence_begin(other.bs_), other.begin_),
325 std::distance<iter_type>(boost::asio::buffer_sequence_begin(other.bs_), other.out_),
326 std::distance<iter_type>(boost::asio::buffer_sequence_begin(other.bs_), other.end_))
330 template<class MutableBufferSequence>
332 buffers_adapter<MutableBufferSequence>::operator=(
333 buffers_adapter&& other) -> buffers_adapter&
335 auto const nbegin = std::distance<iter_type>(
336 boost::asio::buffer_sequence_begin(other.bs_),
338 auto const nout = std::distance<iter_type>(
339 boost::asio::buffer_sequence_begin(other.bs_),
341 auto const nend = std::distance<iter_type>(
342 boost::asio::buffer_sequence_begin(other.bs_),
344 bs_ = std::move(other.bs_);
345 begin_ = std::next(boost::asio::buffer_sequence_begin(bs_), nbegin);
346 out_ = std::next(boost::asio::buffer_sequence_begin(bs_), nout);
347 end_ = std::next(boost::asio::buffer_sequence_begin(bs_), nend);
348 max_size_ = other.max_size_;
349 in_pos_ = other.in_pos_;
350 in_size_ = other.in_size_;
351 out_pos_ = other.out_pos_;
352 out_end_ = other.out_end_;
356 template<class MutableBufferSequence>
358 buffers_adapter<MutableBufferSequence>::operator=(
359 buffers_adapter const& other) -> buffers_adapter&
361 auto const nbegin = std::distance<iter_type>(
362 boost::asio::buffer_sequence_begin(other.bs_),
364 auto const nout = std::distance<iter_type>(
365 boost::asio::buffer_sequence_begin(other.bs_),
367 auto const nend = std::distance<iter_type>(
368 boost::asio::buffer_sequence_begin(other.bs_),
371 begin_ = std::next(boost::asio::buffer_sequence_begin(bs_), nbegin);
372 out_ = std::next(boost::asio::buffer_sequence_begin(bs_), nout);
373 end_ = std::next(boost::asio::buffer_sequence_begin(bs_), nend);
374 max_size_ = other.max_size_;
375 in_pos_ = other.in_pos_;
376 in_size_ = other.in_size_;
377 out_pos_ = other.out_pos_;
378 out_end_ = other.out_end_;
382 template<class MutableBufferSequence>
383 buffers_adapter<MutableBufferSequence>::buffers_adapter(
384 MutableBufferSequence const& bs)
386 , begin_(boost::asio::buffer_sequence_begin(bs_))
387 , out_ (boost::asio::buffer_sequence_begin(bs_))
388 , end_ (boost::asio::buffer_sequence_begin(bs_))
389 , max_size_(boost::asio::buffer_size(bs_))
393 template<class MutableBufferSequence>
395 buffers_adapter<MutableBufferSequence>::prepare(std::size_t n) ->
398 using boost::asio::buffer_size;
400 if(end_ != boost::asio::buffer_sequence_end(bs_))
402 auto size = buffer_size(*end_) - out_pos_;
407 boost::asio::buffer_sequence_end(bs_))
409 size = buffer_size(*end_);
424 out_end_ = out_pos_ + n;
429 BOOST_THROW_EXCEPTION(std::length_error{
431 return mutable_buffers_type{*this};
434 template<class MutableBufferSequence>
436 buffers_adapter<MutableBufferSequence>::commit(std::size_t n)
438 using boost::asio::buffer_size;
441 auto const last = std::prev(end_);
445 buffer_size(*out_) - out_pos_;
460 n = (std::min)(n, out_end_ - out_pos_);
464 if(out_pos_ == buffer_size(*out_))
472 template<class MutableBufferSequence>
475 buffers_adapter<MutableBufferSequence>::data() const ->
478 return const_buffers_type{*this};
481 template<class MutableBufferSequence>
483 buffers_adapter<MutableBufferSequence>::consume(std::size_t n)
485 using boost::asio::buffer_size;
486 while(begin_ != out_)
489 buffer_size(*begin_) - in_pos_;
501 auto const avail = out_pos_ - in_pos_;