2 // detail/consuming_buffers.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11 #ifndef BOOST_ASIO_DETAIL_CONSUMING_BUFFERS_HPP
12 #define BOOST_ASIO_DETAIL_CONSUMING_BUFFERS_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/config.hpp>
21 #include <boost/asio/buffer.hpp>
22 #include <boost/asio/detail/limits.hpp>
24 #include <boost/asio/detail/push_options.hpp>
30 // A proxy iterator for a sub-range in a list of buffers.
31 template <typename Buffer, typename Buffer_Iterator>
32 class consuming_buffers_iterator
35 /// The type used for the distance between two iterators.
36 typedef std::ptrdiff_t difference_type;
38 /// The type of the value pointed to by the iterator.
39 typedef Buffer value_type;
41 /// The type of the result of applying operator->() to the iterator.
42 typedef const Buffer* pointer;
44 /// The type of the result of applying operator*() to the iterator.
45 typedef const Buffer& reference;
47 /// The iterator category.
48 typedef std::forward_iterator_tag iterator_category;
50 // Default constructor creates an end iterator.
51 consuming_buffers_iterator()
56 // Construct with a buffer for the first entry and an iterator
57 // range for the remaining entries.
58 consuming_buffers_iterator(bool at_end, const Buffer& first,
59 Buffer_Iterator begin_remainder, Buffer_Iterator end_remainder,
61 : at_end_(max_size > 0 ? at_end : true),
62 first_(buffer(first, max_size)),
63 begin_remainder_(begin_remainder),
64 end_remainder_(end_remainder),
70 // Dereference an iterator.
71 const Buffer& operator*() const
76 // Dereference an iterator.
77 const Buffer* operator->() const
79 return &dereference();
82 // Increment operator (prefix).
83 consuming_buffers_iterator& operator++()
89 // Increment operator (postfix).
90 consuming_buffers_iterator operator++(int)
92 consuming_buffers_iterator tmp(*this);
97 // Test two iterators for equality.
98 friend bool operator==(const consuming_buffers_iterator& a,
99 const consuming_buffers_iterator& b)
104 // Test two iterators for inequality.
105 friend bool operator!=(const consuming_buffers_iterator& a,
106 const consuming_buffers_iterator& b)
116 if (begin_remainder_ == end_remainder_
117 || offset_ + buffer_size(first_) >= max_size_)
123 offset_ += buffer_size(first_);
124 first_ = buffer(*begin_remainder_++, max_size_ - offset_);
129 bool equal(const consuming_buffers_iterator& other) const
131 if (at_end_ && other.at_end_)
133 return !at_end_ && !other.at_end_
134 && buffer_cast<const void*>(first_)
135 == buffer_cast<const void*>(other.first_)
136 && buffer_size(first_) == buffer_size(other.first_)
137 && begin_remainder_ == other.begin_remainder_
138 && end_remainder_ == other.end_remainder_;
141 const Buffer& dereference() const
148 Buffer_Iterator begin_remainder_;
149 Buffer_Iterator end_remainder_;
151 std::size_t max_size_;
154 // A proxy for a sub-range in a list of buffers.
155 template <typename Buffer, typename Buffers>
156 class consuming_buffers
159 // The type for each element in the list of buffers.
160 typedef Buffer value_type;
162 // A forward-only iterator type that may be used to read elements.
163 typedef consuming_buffers_iterator<Buffer, typename Buffers::const_iterator>
166 // Construct to represent the entire list of buffers.
167 consuming_buffers(const Buffers& buffers)
169 at_end_(buffers_.begin() == buffers_.end()),
170 begin_remainder_(buffers_.begin()),
171 max_size_((std::numeric_limits<std::size_t>::max)())
175 first_ = *buffers_.begin();
181 consuming_buffers(const consuming_buffers& other)
182 : buffers_(other.buffers_),
183 at_end_(other.at_end_),
184 first_(other.first_),
185 begin_remainder_(buffers_.begin()),
186 max_size_(other.max_size_)
188 typename Buffers::const_iterator first = other.buffers_.begin();
189 typename Buffers::const_iterator second = other.begin_remainder_;
190 std::advance(begin_remainder_, std::distance(first, second));
193 // Assignment operator.
194 consuming_buffers& operator=(const consuming_buffers& other)
196 buffers_ = other.buffers_;
197 at_end_ = other.at_end_;
198 first_ = other.first_;
199 begin_remainder_ = buffers_.begin();
200 typename Buffers::const_iterator first = other.buffers_.begin();
201 typename Buffers::const_iterator second = other.begin_remainder_;
202 std::advance(begin_remainder_, std::distance(first, second));
203 max_size_ = other.max_size_;
207 // Get a forward-only iterator to the first element.
208 const_iterator begin() const
210 return const_iterator(at_end_, first_,
211 begin_remainder_, buffers_.end(), max_size_);
214 // Get a forward-only iterator for one past the last element.
215 const_iterator end() const
217 return const_iterator();
220 // Set the maximum size for a single transfer.
221 void prepare(std::size_t max_size)
223 max_size_ = max_size;
226 // Consume the specified number of bytes from the buffers.
227 void consume(std::size_t size)
229 // Remove buffers from the start until the specified size is reached.
230 while (size > 0 && !at_end_)
232 if (buffer_size(first_) <= size)
234 size -= buffer_size(first_);
235 if (begin_remainder_ == buffers_.end())
238 first_ = *begin_remainder_++;
242 first_ = first_ + size;
247 // Remove any more empty buffers at the start.
248 while (!at_end_ && buffer_size(first_) == 0)
250 if (begin_remainder_ == buffers_.end())
253 first_ = *begin_remainder_++;
261 typename Buffers::const_iterator begin_remainder_;
262 std::size_t max_size_;
265 // Specialisation for null_buffers to ensure that the null_buffers type is
266 // always passed through to the underlying read or write operation.
267 template <typename Buffer>
268 class consuming_buffers<Buffer, boost::asio::null_buffers>
269 : public boost::asio::null_buffers
272 consuming_buffers(const boost::asio::null_buffers&)
277 void prepare(std::size_t)
282 void consume(std::size_t)
288 } // namespace detail
292 #include <boost/asio/detail/pop_options.hpp>
294 #endif // BOOST_ASIO_DETAIL_CONSUMING_BUFFERS_HPP