2 // Copyright (c) 2013-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)
8 #ifndef BEAST_IMPL_BUFFERS_ADAPTER_IPP
9 #define BEAST_IMPL_BUFFERS_ADAPTER_IPP
11 #include <beast/core/detail/type_traits.hpp>
12 #include <boost/asio/buffer.hpp>
17 #include <type_traits>
21 template<class MutableBufferSequence>
22 class buffers_adapter<MutableBufferSequence>::
25 buffers_adapter const* ba_;
28 using value_type = boost::asio::const_buffer;
32 const_buffers_type() = delete;
34 const_buffers_type const&) = default;
35 const_buffers_type& operator=(
36 const_buffers_type const&) = default;
45 friend class buffers_adapter;
47 const_buffers_type(buffers_adapter const& ba)
53 template<class MutableBufferSequence>
54 class buffers_adapter<MutableBufferSequence>::
55 const_buffers_type::const_iterator
58 buffers_adapter const* ba_ = nullptr;
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;
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;
75 operator==(const_iterator const& other) const
77 return ba_ == other.ba_ &&
82 operator!=(const_iterator const& other) const
84 return !(*this == other);
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);
99 operator->() const = delete;
132 friend class const_buffers_type;
134 const_iterator(buffers_adapter const& ba,
142 template<class MutableBufferSequence>
145 buffers_adapter<MutableBufferSequence>::const_buffers_type::begin() const ->
148 return const_iterator{*ba_, ba_->begin_};
151 template<class MutableBufferSequence>
154 buffers_adapter<MutableBufferSequence>::const_buffers_type::end() const ->
157 return const_iterator{*ba_, ba_->out_ ==
158 ba_->end_ ? ba_->end_ : std::next(ba_->out_)};
161 //------------------------------------------------------------------------------
163 template<class MutableBufferSequence>
164 class buffers_adapter<MutableBufferSequence>::
167 buffers_adapter const* ba_;
170 using value_type = boost::asio::mutable_buffer;
172 class const_iterator;
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;
187 friend class buffers_adapter;
189 mutable_buffers_type(
190 buffers_adapter const& ba)
196 template<class MutableBufferSequence>
197 class buffers_adapter<MutableBufferSequence>::
198 mutable_buffers_type::const_iterator
201 buffers_adapter const* ba_ = nullptr;
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;
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;
218 operator==(const_iterator const& other) const
220 return ba_ == other.ba_ &&
225 operator!=(const_iterator const& other) const
227 return !(*this == other);
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);
242 operator->() const = delete;
275 friend class mutable_buffers_type;
277 const_iterator(buffers_adapter const& ba,
285 template<class MutableBufferSequence>
288 buffers_adapter<MutableBufferSequence>::mutable_buffers_type::begin() const ->
291 return const_iterator{*ba_, ba_->out_};
294 template<class MutableBufferSequence>
297 buffers_adapter<MutableBufferSequence>::mutable_buffers_type::end() const ->
300 return const_iterator{*ba_, ba_->end_};
303 //------------------------------------------------------------------------------
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_))
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_))
325 template<class MutableBufferSequence>
327 buffers_adapter<MutableBufferSequence>::operator=(
328 buffers_adapter&& other) -> buffers_adapter&
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_;
348 template<class MutableBufferSequence>
350 buffers_adapter<MutableBufferSequence>::operator=(
351 buffers_adapter const& other) -> buffers_adapter&
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_);
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_;
371 template<class MutableBufferSequence>
372 buffers_adapter<MutableBufferSequence>::buffers_adapter(
373 MutableBufferSequence const& bs)
375 , begin_(bs_.begin())
378 , max_size_(boost::asio::buffer_size(bs_))
382 template<class MutableBufferSequence>
384 buffers_adapter<MutableBufferSequence>::prepare(std::size_t n) ->
387 using boost::asio::buffer_size;
389 if(end_ != bs_.end())
391 auto size = buffer_size(*end_) - out_pos_;
395 while(++end_ != bs_.end())
397 size = buffer_size(*end_);
412 out_end_ = out_pos_ + n;
417 throw detail::make_exception<std::length_error>(
418 "no space", __FILE__, __LINE__);
419 return mutable_buffers_type{*this};
422 template<class MutableBufferSequence>
424 buffers_adapter<MutableBufferSequence>::commit(std::size_t n)
426 using boost::asio::buffer_size;
429 auto const last = std::prev(end_);
433 buffer_size(*out_) - out_pos_;
448 n = (std::min)(n, out_end_ - out_pos_);
452 if(out_pos_ == buffer_size(*out_))
460 template<class MutableBufferSequence>
463 buffers_adapter<MutableBufferSequence>::data() const ->
466 return const_buffers_type{*this};
469 template<class MutableBufferSequence>
471 buffers_adapter<MutableBufferSequence>::consume(std::size_t n)
473 using boost::asio::buffer_size;
474 while(begin_ != out_)
477 buffer_size(*begin_) - in_pos_;
489 auto const avail = out_pos_ - in_pos_;