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_DETAIL_PREPARED_BUFFERS_HPP
9 #define BEAST_DETAIL_PREPARED_BUFFERS_HPP
11 #include <beast/core/prepare_buffer.hpp>
12 #include <boost/asio/buffer.hpp>
17 #include <type_traits>
23 /** A buffer sequence adapter that shortens the sequence size.
25 The class adapts a buffer sequence to efficiently represent
26 a shorter subset of the original list of buffers starting
27 with the first byte of the original sequence.
29 @tparam BufferSequence The buffer sequence to adapt.
31 template<class BufferSequence>
32 class prepared_buffers
35 typename BufferSequence::const_iterator;
42 template<class Deduced>
43 prepared_buffers(Deduced&& other,
44 std::size_t nback, std::size_t nend)
45 : bs_(std::forward<Deduced>(other).bs_)
46 , back_(std::next(bs_.begin(), nback))
47 , end_(std::next(bs_.begin(), nend))
56 /// The type for each element in the list of buffers.
57 using value_type = typename std::conditional<
58 std::is_convertible<typename
59 std::iterator_traits<iter_type>::value_type,
60 boost::asio::mutable_buffer>::value,
61 boost::asio::mutable_buffer,
62 boost::asio::const_buffer>::type;
65 /// A bidirectional iterator type that may be used to read elements.
66 using const_iterator = implementation_defined;
74 prepared_buffers(prepared_buffers&&);
77 prepared_buffers(prepared_buffers const&);
80 prepared_buffers& operator=(prepared_buffers&&);
83 prepared_buffers& operator=(prepared_buffers const&);
85 /** Construct a shortened buffer sequence.
87 @param n The maximum number of bytes in the wrapped
88 sequence. If this is larger than the size of passed,
89 buffers, the resulting sequence will represent the
90 entire input sequence.
92 @param buffers The buffer sequence to adapt. A copy of
93 the sequence will be made, but ownership of the underlying
94 memory is not transferred.
96 prepared_buffers(std::size_t n, BufferSequence const& buffers);
98 /// Get a bidirectional iterator to the first element.
102 /// Get a bidirectional iterator to one past the last element.
107 template<class BufferSequence>
108 class prepared_buffers<BufferSequence>::const_iterator
110 friend class prepared_buffers<BufferSequence>;
113 typename BufferSequence::const_iterator;
115 prepared_buffers const* b_ = nullptr;
116 typename BufferSequence::const_iterator it_;
119 using value_type = typename std::conditional<
120 std::is_convertible<typename
121 std::iterator_traits<iter_type>::value_type,
122 boost::asio::mutable_buffer>::value,
123 boost::asio::mutable_buffer,
124 boost::asio::const_buffer>::type;
125 using pointer = value_type const*;
126 using reference = value_type;
127 using difference_type = std::ptrdiff_t;
128 using iterator_category =
129 std::bidirectional_iterator_tag;
131 const_iterator() = default;
132 const_iterator(const_iterator&& other);
133 const_iterator(const_iterator const& other);
134 const_iterator& operator=(const_iterator&& other);
135 const_iterator& operator=(const_iterator const& other);
138 operator==(const_iterator const& other) const
140 return b_ == other.b_ && it_ == other.it_;
144 operator!=(const_iterator const& other) const
146 return !(*this == other);
153 return prepare_buffer(b_->size_, *it_);
158 operator->() const = delete;
191 const_iterator(prepared_buffers const& b,
194 , it_(at_end ? b.end_ : b.bs_.begin())
199 template<class BufferSequence>
201 prepared_buffers<BufferSequence>::
204 for(end_ = bs_.begin(); end_ != bs_.end(); ++end_)
207 boost::asio::buffer_size(*end_);
220 template<class BufferSequence>
221 prepared_buffers<BufferSequence>::const_iterator::
222 const_iterator(const_iterator&& other)
224 , it_(std::move(other.it_))
228 template<class BufferSequence>
229 prepared_buffers<BufferSequence>::const_iterator::
230 const_iterator(const_iterator const& other)
236 template<class BufferSequence>
238 prepared_buffers<BufferSequence>::const_iterator::
239 operator=(const_iterator&& other) ->
243 it_ = std::move(other.it_);
247 template<class BufferSequence>
249 prepared_buffers<BufferSequence>::const_iterator::
250 operator=(const_iterator const& other) ->
260 template<class BufferSequence>
261 prepared_buffers<BufferSequence>::
262 prepared_buffers(prepared_buffers&& other)
263 : prepared_buffers(std::move(other),
264 std::distance<iter_type>(other.bs_.begin(), other.back_),
265 std::distance<iter_type>(other.bs_.begin(), other.end_))
269 template<class BufferSequence>
270 prepared_buffers<BufferSequence>::
271 prepared_buffers(prepared_buffers const& other)
272 : prepared_buffers(other,
273 std::distance<iter_type>(other.bs_.begin(), other.back_),
274 std::distance<iter_type>(other.bs_.begin(), other.end_))
278 template<class BufferSequence>
280 prepared_buffers<BufferSequence>::
281 operator=(prepared_buffers&& other) ->
284 auto const nback = std::distance<iter_type>(
285 other.bs_.begin(), other.back_);
286 auto const nend = std::distance<iter_type>(
287 other.bs_.begin(), other.end_);
288 bs_ = std::move(other.bs_);
289 back_ = std::next(bs_.begin(), nback);
290 end_ = std::next(bs_.begin(), nend);
295 template<class BufferSequence>
297 prepared_buffers<BufferSequence>::
298 operator=(prepared_buffers const& other) ->
301 auto const nback = std::distance<iter_type>(
302 other.bs_.begin(), other.back_);
303 auto const nend = std::distance<iter_type>(
304 other.bs_.begin(), other.end_);
306 back_ = std::next(bs_.begin(), nback);
307 end_ = std::next(bs_.begin(), nend);
312 template<class BufferSequence>
313 prepared_buffers<BufferSequence>::
314 prepared_buffers(std::size_t n, BufferSequence const& bs)
320 template<class BufferSequence>
323 prepared_buffers<BufferSequence>::begin() const ->
326 return const_iterator{*this, false};
329 template<class BufferSequence>
332 prepared_buffers<BufferSequence>::end() const ->
335 return const_iterator{*this, true};