Chris@16
|
1 //
|
Chris@16
|
2 // buffers_iterator.hpp
|
Chris@16
|
3 // ~~~~~~~~~~~~~~~~~~~~
|
Chris@16
|
4 //
|
Chris@101
|
5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
Chris@16
|
6 //
|
Chris@16
|
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
9 //
|
Chris@16
|
10
|
Chris@16
|
11 #ifndef BOOST_ASIO_BUFFERS_ITERATOR_HPP
|
Chris@16
|
12 #define BOOST_ASIO_BUFFERS_ITERATOR_HPP
|
Chris@16
|
13
|
Chris@16
|
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
Chris@16
|
15 # pragma once
|
Chris@16
|
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
Chris@16
|
17
|
Chris@16
|
18 #include <boost/asio/detail/config.hpp>
|
Chris@16
|
19 #include <cstddef>
|
Chris@16
|
20 #include <iterator>
|
Chris@16
|
21 #include <boost/asio/buffer.hpp>
|
Chris@16
|
22 #include <boost/asio/detail/assert.hpp>
|
Chris@16
|
23 #include <boost/asio/detail/type_traits.hpp>
|
Chris@16
|
24
|
Chris@16
|
25 #include <boost/asio/detail/push_options.hpp>
|
Chris@16
|
26
|
Chris@16
|
27 namespace boost {
|
Chris@16
|
28 namespace asio {
|
Chris@16
|
29
|
Chris@16
|
30 namespace detail
|
Chris@16
|
31 {
|
Chris@16
|
32 template <bool IsMutable>
|
Chris@16
|
33 struct buffers_iterator_types_helper;
|
Chris@16
|
34
|
Chris@16
|
35 template <>
|
Chris@16
|
36 struct buffers_iterator_types_helper<false>
|
Chris@16
|
37 {
|
Chris@16
|
38 typedef const_buffer buffer_type;
|
Chris@16
|
39 template <typename ByteType>
|
Chris@16
|
40 struct byte_type
|
Chris@16
|
41 {
|
Chris@16
|
42 typedef typename add_const<ByteType>::type type;
|
Chris@16
|
43 };
|
Chris@16
|
44 };
|
Chris@16
|
45
|
Chris@16
|
46 template <>
|
Chris@16
|
47 struct buffers_iterator_types_helper<true>
|
Chris@16
|
48 {
|
Chris@16
|
49 typedef mutable_buffer buffer_type;
|
Chris@16
|
50 template <typename ByteType>
|
Chris@16
|
51 struct byte_type
|
Chris@16
|
52 {
|
Chris@16
|
53 typedef ByteType type;
|
Chris@16
|
54 };
|
Chris@16
|
55 };
|
Chris@16
|
56
|
Chris@16
|
57 template <typename BufferSequence, typename ByteType>
|
Chris@16
|
58 struct buffers_iterator_types
|
Chris@16
|
59 {
|
Chris@16
|
60 enum
|
Chris@16
|
61 {
|
Chris@16
|
62 is_mutable = is_convertible<
|
Chris@16
|
63 typename BufferSequence::value_type,
|
Chris@16
|
64 mutable_buffer>::value
|
Chris@16
|
65 };
|
Chris@16
|
66 typedef buffers_iterator_types_helper<is_mutable> helper;
|
Chris@16
|
67 typedef typename helper::buffer_type buffer_type;
|
Chris@16
|
68 typedef typename helper::template byte_type<ByteType>::type byte_type;
|
Chris@16
|
69 };
|
Chris@16
|
70 }
|
Chris@16
|
71
|
Chris@16
|
72 /// A random access iterator over the bytes in a buffer sequence.
|
Chris@16
|
73 template <typename BufferSequence, typename ByteType = char>
|
Chris@16
|
74 class buffers_iterator
|
Chris@16
|
75 {
|
Chris@16
|
76 private:
|
Chris@16
|
77 typedef typename detail::buffers_iterator_types<
|
Chris@16
|
78 BufferSequence, ByteType>::buffer_type buffer_type;
|
Chris@16
|
79
|
Chris@16
|
80 public:
|
Chris@16
|
81 /// The type used for the distance between two iterators.
|
Chris@16
|
82 typedef std::ptrdiff_t difference_type;
|
Chris@16
|
83
|
Chris@16
|
84 /// The type of the value pointed to by the iterator.
|
Chris@16
|
85 typedef ByteType value_type;
|
Chris@16
|
86
|
Chris@16
|
87 #if defined(GENERATING_DOCUMENTATION)
|
Chris@16
|
88 /// The type of the result of applying operator->() to the iterator.
|
Chris@16
|
89 /**
|
Chris@16
|
90 * If the buffer sequence stores buffer objects that are convertible to
|
Chris@16
|
91 * mutable_buffer, this is a pointer to a non-const ByteType. Otherwise, a
|
Chris@16
|
92 * pointer to a const ByteType.
|
Chris@16
|
93 */
|
Chris@16
|
94 typedef const_or_non_const_ByteType* pointer;
|
Chris@16
|
95 #else // defined(GENERATING_DOCUMENTATION)
|
Chris@16
|
96 typedef typename detail::buffers_iterator_types<
|
Chris@16
|
97 BufferSequence, ByteType>::byte_type* pointer;
|
Chris@16
|
98 #endif // defined(GENERATING_DOCUMENTATION)
|
Chris@16
|
99
|
Chris@16
|
100 #if defined(GENERATING_DOCUMENTATION)
|
Chris@16
|
101 /// The type of the result of applying operator*() to the iterator.
|
Chris@16
|
102 /**
|
Chris@16
|
103 * If the buffer sequence stores buffer objects that are convertible to
|
Chris@16
|
104 * mutable_buffer, this is a reference to a non-const ByteType. Otherwise, a
|
Chris@16
|
105 * reference to a const ByteType.
|
Chris@16
|
106 */
|
Chris@16
|
107 typedef const_or_non_const_ByteType& reference;
|
Chris@16
|
108 #else // defined(GENERATING_DOCUMENTATION)
|
Chris@16
|
109 typedef typename detail::buffers_iterator_types<
|
Chris@16
|
110 BufferSequence, ByteType>::byte_type& reference;
|
Chris@16
|
111 #endif // defined(GENERATING_DOCUMENTATION)
|
Chris@16
|
112
|
Chris@16
|
113 /// The iterator category.
|
Chris@16
|
114 typedef std::random_access_iterator_tag iterator_category;
|
Chris@16
|
115
|
Chris@16
|
116 /// Default constructor. Creates an iterator in an undefined state.
|
Chris@16
|
117 buffers_iterator()
|
Chris@16
|
118 : current_buffer_(),
|
Chris@16
|
119 current_buffer_position_(0),
|
Chris@16
|
120 begin_(),
|
Chris@16
|
121 current_(),
|
Chris@16
|
122 end_(),
|
Chris@16
|
123 position_(0)
|
Chris@16
|
124 {
|
Chris@16
|
125 }
|
Chris@16
|
126
|
Chris@16
|
127 /// Construct an iterator representing the beginning of the buffers' data.
|
Chris@16
|
128 static buffers_iterator begin(const BufferSequence& buffers)
|
Chris@16
|
129 #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
|
Chris@16
|
130 __attribute__ ((__noinline__))
|
Chris@16
|
131 #endif // defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
|
Chris@16
|
132 {
|
Chris@16
|
133 buffers_iterator new_iter;
|
Chris@16
|
134 new_iter.begin_ = buffers.begin();
|
Chris@16
|
135 new_iter.current_ = buffers.begin();
|
Chris@16
|
136 new_iter.end_ = buffers.end();
|
Chris@16
|
137 while (new_iter.current_ != new_iter.end_)
|
Chris@16
|
138 {
|
Chris@16
|
139 new_iter.current_buffer_ = *new_iter.current_;
|
Chris@16
|
140 if (boost::asio::buffer_size(new_iter.current_buffer_) > 0)
|
Chris@16
|
141 break;
|
Chris@16
|
142 ++new_iter.current_;
|
Chris@16
|
143 }
|
Chris@16
|
144 return new_iter;
|
Chris@16
|
145 }
|
Chris@16
|
146
|
Chris@16
|
147 /// Construct an iterator representing the end of the buffers' data.
|
Chris@16
|
148 static buffers_iterator end(const BufferSequence& buffers)
|
Chris@16
|
149 #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
|
Chris@16
|
150 __attribute__ ((__noinline__))
|
Chris@16
|
151 #endif // defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
|
Chris@16
|
152 {
|
Chris@16
|
153 buffers_iterator new_iter;
|
Chris@16
|
154 new_iter.begin_ = buffers.begin();
|
Chris@16
|
155 new_iter.current_ = buffers.begin();
|
Chris@16
|
156 new_iter.end_ = buffers.end();
|
Chris@16
|
157 while (new_iter.current_ != new_iter.end_)
|
Chris@16
|
158 {
|
Chris@16
|
159 buffer_type buffer = *new_iter.current_;
|
Chris@16
|
160 new_iter.position_ += boost::asio::buffer_size(buffer);
|
Chris@16
|
161 ++new_iter.current_;
|
Chris@16
|
162 }
|
Chris@16
|
163 return new_iter;
|
Chris@16
|
164 }
|
Chris@16
|
165
|
Chris@16
|
166 /// Dereference an iterator.
|
Chris@16
|
167 reference operator*() const
|
Chris@16
|
168 {
|
Chris@16
|
169 return dereference();
|
Chris@16
|
170 }
|
Chris@16
|
171
|
Chris@16
|
172 /// Dereference an iterator.
|
Chris@16
|
173 pointer operator->() const
|
Chris@16
|
174 {
|
Chris@16
|
175 return &dereference();
|
Chris@16
|
176 }
|
Chris@16
|
177
|
Chris@16
|
178 /// Access an individual element.
|
Chris@16
|
179 reference operator[](std::ptrdiff_t difference) const
|
Chris@16
|
180 {
|
Chris@16
|
181 buffers_iterator tmp(*this);
|
Chris@16
|
182 tmp.advance(difference);
|
Chris@16
|
183 return *tmp;
|
Chris@16
|
184 }
|
Chris@16
|
185
|
Chris@16
|
186 /// Increment operator (prefix).
|
Chris@16
|
187 buffers_iterator& operator++()
|
Chris@16
|
188 {
|
Chris@16
|
189 increment();
|
Chris@16
|
190 return *this;
|
Chris@16
|
191 }
|
Chris@16
|
192
|
Chris@16
|
193 /// Increment operator (postfix).
|
Chris@16
|
194 buffers_iterator operator++(int)
|
Chris@16
|
195 {
|
Chris@16
|
196 buffers_iterator tmp(*this);
|
Chris@16
|
197 ++*this;
|
Chris@16
|
198 return tmp;
|
Chris@16
|
199 }
|
Chris@16
|
200
|
Chris@16
|
201 /// Decrement operator (prefix).
|
Chris@16
|
202 buffers_iterator& operator--()
|
Chris@16
|
203 {
|
Chris@16
|
204 decrement();
|
Chris@16
|
205 return *this;
|
Chris@16
|
206 }
|
Chris@16
|
207
|
Chris@16
|
208 /// Decrement operator (postfix).
|
Chris@16
|
209 buffers_iterator operator--(int)
|
Chris@16
|
210 {
|
Chris@16
|
211 buffers_iterator tmp(*this);
|
Chris@16
|
212 --*this;
|
Chris@16
|
213 return tmp;
|
Chris@16
|
214 }
|
Chris@16
|
215
|
Chris@16
|
216 /// Addition operator.
|
Chris@16
|
217 buffers_iterator& operator+=(std::ptrdiff_t difference)
|
Chris@16
|
218 {
|
Chris@16
|
219 advance(difference);
|
Chris@16
|
220 return *this;
|
Chris@16
|
221 }
|
Chris@16
|
222
|
Chris@16
|
223 /// Subtraction operator.
|
Chris@16
|
224 buffers_iterator& operator-=(std::ptrdiff_t difference)
|
Chris@16
|
225 {
|
Chris@16
|
226 advance(-difference);
|
Chris@16
|
227 return *this;
|
Chris@16
|
228 }
|
Chris@16
|
229
|
Chris@16
|
230 /// Addition operator.
|
Chris@16
|
231 friend buffers_iterator operator+(const buffers_iterator& iter,
|
Chris@16
|
232 std::ptrdiff_t difference)
|
Chris@16
|
233 {
|
Chris@16
|
234 buffers_iterator tmp(iter);
|
Chris@16
|
235 tmp.advance(difference);
|
Chris@16
|
236 return tmp;
|
Chris@16
|
237 }
|
Chris@16
|
238
|
Chris@16
|
239 /// Addition operator.
|
Chris@16
|
240 friend buffers_iterator operator+(std::ptrdiff_t difference,
|
Chris@16
|
241 const buffers_iterator& iter)
|
Chris@16
|
242 {
|
Chris@16
|
243 buffers_iterator tmp(iter);
|
Chris@16
|
244 tmp.advance(difference);
|
Chris@16
|
245 return tmp;
|
Chris@16
|
246 }
|
Chris@16
|
247
|
Chris@16
|
248 /// Subtraction operator.
|
Chris@16
|
249 friend buffers_iterator operator-(const buffers_iterator& iter,
|
Chris@16
|
250 std::ptrdiff_t difference)
|
Chris@16
|
251 {
|
Chris@16
|
252 buffers_iterator tmp(iter);
|
Chris@16
|
253 tmp.advance(-difference);
|
Chris@16
|
254 return tmp;
|
Chris@16
|
255 }
|
Chris@16
|
256
|
Chris@16
|
257 /// Subtraction operator.
|
Chris@16
|
258 friend std::ptrdiff_t operator-(const buffers_iterator& a,
|
Chris@16
|
259 const buffers_iterator& b)
|
Chris@16
|
260 {
|
Chris@16
|
261 return b.distance_to(a);
|
Chris@16
|
262 }
|
Chris@16
|
263
|
Chris@16
|
264 /// Test two iterators for equality.
|
Chris@16
|
265 friend bool operator==(const buffers_iterator& a, const buffers_iterator& b)
|
Chris@16
|
266 {
|
Chris@16
|
267 return a.equal(b);
|
Chris@16
|
268 }
|
Chris@16
|
269
|
Chris@16
|
270 /// Test two iterators for inequality.
|
Chris@16
|
271 friend bool operator!=(const buffers_iterator& a, const buffers_iterator& b)
|
Chris@16
|
272 {
|
Chris@16
|
273 return !a.equal(b);
|
Chris@16
|
274 }
|
Chris@16
|
275
|
Chris@16
|
276 /// Compare two iterators.
|
Chris@16
|
277 friend bool operator<(const buffers_iterator& a, const buffers_iterator& b)
|
Chris@16
|
278 {
|
Chris@16
|
279 return a.distance_to(b) > 0;
|
Chris@16
|
280 }
|
Chris@16
|
281
|
Chris@16
|
282 /// Compare two iterators.
|
Chris@16
|
283 friend bool operator<=(const buffers_iterator& a, const buffers_iterator& b)
|
Chris@16
|
284 {
|
Chris@16
|
285 return !(b < a);
|
Chris@16
|
286 }
|
Chris@16
|
287
|
Chris@16
|
288 /// Compare two iterators.
|
Chris@16
|
289 friend bool operator>(const buffers_iterator& a, const buffers_iterator& b)
|
Chris@16
|
290 {
|
Chris@16
|
291 return b < a;
|
Chris@16
|
292 }
|
Chris@16
|
293
|
Chris@16
|
294 /// Compare two iterators.
|
Chris@16
|
295 friend bool operator>=(const buffers_iterator& a, const buffers_iterator& b)
|
Chris@16
|
296 {
|
Chris@16
|
297 return !(a < b);
|
Chris@16
|
298 }
|
Chris@16
|
299
|
Chris@16
|
300 private:
|
Chris@16
|
301 // Dereference the iterator.
|
Chris@16
|
302 reference dereference() const
|
Chris@16
|
303 {
|
Chris@16
|
304 return buffer_cast<pointer>(current_buffer_)[current_buffer_position_];
|
Chris@16
|
305 }
|
Chris@16
|
306
|
Chris@16
|
307 // Compare two iterators for equality.
|
Chris@16
|
308 bool equal(const buffers_iterator& other) const
|
Chris@16
|
309 {
|
Chris@16
|
310 return position_ == other.position_;
|
Chris@16
|
311 }
|
Chris@16
|
312
|
Chris@16
|
313 // Increment the iterator.
|
Chris@16
|
314 void increment()
|
Chris@16
|
315 {
|
Chris@16
|
316 BOOST_ASIO_ASSERT(current_ != end_ && "iterator out of bounds");
|
Chris@16
|
317 ++position_;
|
Chris@16
|
318
|
Chris@16
|
319 // Check if the increment can be satisfied by the current buffer.
|
Chris@16
|
320 ++current_buffer_position_;
|
Chris@16
|
321 if (current_buffer_position_ != boost::asio::buffer_size(current_buffer_))
|
Chris@16
|
322 return;
|
Chris@16
|
323
|
Chris@16
|
324 // Find the next non-empty buffer.
|
Chris@16
|
325 ++current_;
|
Chris@16
|
326 current_buffer_position_ = 0;
|
Chris@16
|
327 while (current_ != end_)
|
Chris@16
|
328 {
|
Chris@16
|
329 current_buffer_ = *current_;
|
Chris@16
|
330 if (boost::asio::buffer_size(current_buffer_) > 0)
|
Chris@16
|
331 return;
|
Chris@16
|
332 ++current_;
|
Chris@16
|
333 }
|
Chris@16
|
334 }
|
Chris@16
|
335
|
Chris@16
|
336 // Decrement the iterator.
|
Chris@16
|
337 void decrement()
|
Chris@16
|
338 {
|
Chris@16
|
339 BOOST_ASIO_ASSERT(position_ > 0 && "iterator out of bounds");
|
Chris@16
|
340 --position_;
|
Chris@16
|
341
|
Chris@16
|
342 // Check if the decrement can be satisfied by the current buffer.
|
Chris@16
|
343 if (current_buffer_position_ != 0)
|
Chris@16
|
344 {
|
Chris@16
|
345 --current_buffer_position_;
|
Chris@16
|
346 return;
|
Chris@16
|
347 }
|
Chris@16
|
348
|
Chris@16
|
349 // Find the previous non-empty buffer.
|
Chris@16
|
350 typename BufferSequence::const_iterator iter = current_;
|
Chris@16
|
351 while (iter != begin_)
|
Chris@16
|
352 {
|
Chris@16
|
353 --iter;
|
Chris@16
|
354 buffer_type buffer = *iter;
|
Chris@16
|
355 std::size_t buffer_size = boost::asio::buffer_size(buffer);
|
Chris@16
|
356 if (buffer_size > 0)
|
Chris@16
|
357 {
|
Chris@16
|
358 current_ = iter;
|
Chris@16
|
359 current_buffer_ = buffer;
|
Chris@16
|
360 current_buffer_position_ = buffer_size - 1;
|
Chris@16
|
361 return;
|
Chris@16
|
362 }
|
Chris@16
|
363 }
|
Chris@16
|
364 }
|
Chris@16
|
365
|
Chris@16
|
366 // Advance the iterator by the specified distance.
|
Chris@16
|
367 void advance(std::ptrdiff_t n)
|
Chris@16
|
368 {
|
Chris@16
|
369 if (n > 0)
|
Chris@16
|
370 {
|
Chris@16
|
371 BOOST_ASIO_ASSERT(current_ != end_ && "iterator out of bounds");
|
Chris@16
|
372 for (;;)
|
Chris@16
|
373 {
|
Chris@16
|
374 std::ptrdiff_t current_buffer_balance
|
Chris@16
|
375 = boost::asio::buffer_size(current_buffer_)
|
Chris@16
|
376 - current_buffer_position_;
|
Chris@16
|
377
|
Chris@16
|
378 // Check if the advance can be satisfied by the current buffer.
|
Chris@16
|
379 if (current_buffer_balance > n)
|
Chris@16
|
380 {
|
Chris@16
|
381 position_ += n;
|
Chris@16
|
382 current_buffer_position_ += n;
|
Chris@16
|
383 return;
|
Chris@16
|
384 }
|
Chris@16
|
385
|
Chris@16
|
386 // Update position.
|
Chris@16
|
387 n -= current_buffer_balance;
|
Chris@16
|
388 position_ += current_buffer_balance;
|
Chris@16
|
389
|
Chris@16
|
390 // Move to next buffer. If it is empty then it will be skipped on the
|
Chris@16
|
391 // next iteration of this loop.
|
Chris@16
|
392 if (++current_ == end_)
|
Chris@16
|
393 {
|
Chris@16
|
394 BOOST_ASIO_ASSERT(n == 0 && "iterator out of bounds");
|
Chris@16
|
395 current_buffer_ = buffer_type();
|
Chris@16
|
396 current_buffer_position_ = 0;
|
Chris@16
|
397 return;
|
Chris@16
|
398 }
|
Chris@16
|
399 current_buffer_ = *current_;
|
Chris@16
|
400 current_buffer_position_ = 0;
|
Chris@16
|
401 }
|
Chris@16
|
402 }
|
Chris@16
|
403 else if (n < 0)
|
Chris@16
|
404 {
|
Chris@16
|
405 std::size_t abs_n = -n;
|
Chris@16
|
406 BOOST_ASIO_ASSERT(position_ >= abs_n && "iterator out of bounds");
|
Chris@16
|
407 for (;;)
|
Chris@16
|
408 {
|
Chris@16
|
409 // Check if the advance can be satisfied by the current buffer.
|
Chris@16
|
410 if (current_buffer_position_ >= abs_n)
|
Chris@16
|
411 {
|
Chris@16
|
412 position_ -= abs_n;
|
Chris@16
|
413 current_buffer_position_ -= abs_n;
|
Chris@16
|
414 return;
|
Chris@16
|
415 }
|
Chris@16
|
416
|
Chris@16
|
417 // Update position.
|
Chris@16
|
418 abs_n -= current_buffer_position_;
|
Chris@16
|
419 position_ -= current_buffer_position_;
|
Chris@16
|
420
|
Chris@16
|
421 // Check if we've reached the beginning of the buffers.
|
Chris@16
|
422 if (current_ == begin_)
|
Chris@16
|
423 {
|
Chris@16
|
424 BOOST_ASIO_ASSERT(abs_n == 0 && "iterator out of bounds");
|
Chris@16
|
425 current_buffer_position_ = 0;
|
Chris@16
|
426 return;
|
Chris@16
|
427 }
|
Chris@16
|
428
|
Chris@16
|
429 // Find the previous non-empty buffer.
|
Chris@16
|
430 typename BufferSequence::const_iterator iter = current_;
|
Chris@16
|
431 while (iter != begin_)
|
Chris@16
|
432 {
|
Chris@16
|
433 --iter;
|
Chris@16
|
434 buffer_type buffer = *iter;
|
Chris@16
|
435 std::size_t buffer_size = boost::asio::buffer_size(buffer);
|
Chris@16
|
436 if (buffer_size > 0)
|
Chris@16
|
437 {
|
Chris@16
|
438 current_ = iter;
|
Chris@16
|
439 current_buffer_ = buffer;
|
Chris@16
|
440 current_buffer_position_ = buffer_size;
|
Chris@16
|
441 break;
|
Chris@16
|
442 }
|
Chris@16
|
443 }
|
Chris@16
|
444 }
|
Chris@16
|
445 }
|
Chris@16
|
446 }
|
Chris@16
|
447
|
Chris@16
|
448 // Determine the distance between two iterators.
|
Chris@16
|
449 std::ptrdiff_t distance_to(const buffers_iterator& other) const
|
Chris@16
|
450 {
|
Chris@16
|
451 return other.position_ - position_;
|
Chris@16
|
452 }
|
Chris@16
|
453
|
Chris@16
|
454 buffer_type current_buffer_;
|
Chris@16
|
455 std::size_t current_buffer_position_;
|
Chris@16
|
456 typename BufferSequence::const_iterator begin_;
|
Chris@16
|
457 typename BufferSequence::const_iterator current_;
|
Chris@16
|
458 typename BufferSequence::const_iterator end_;
|
Chris@16
|
459 std::size_t position_;
|
Chris@16
|
460 };
|
Chris@16
|
461
|
Chris@16
|
462 /// Construct an iterator representing the beginning of the buffers' data.
|
Chris@16
|
463 template <typename BufferSequence>
|
Chris@16
|
464 inline buffers_iterator<BufferSequence> buffers_begin(
|
Chris@16
|
465 const BufferSequence& buffers)
|
Chris@16
|
466 {
|
Chris@16
|
467 return buffers_iterator<BufferSequence>::begin(buffers);
|
Chris@16
|
468 }
|
Chris@16
|
469
|
Chris@16
|
470 /// Construct an iterator representing the end of the buffers' data.
|
Chris@16
|
471 template <typename BufferSequence>
|
Chris@16
|
472 inline buffers_iterator<BufferSequence> buffers_end(
|
Chris@16
|
473 const BufferSequence& buffers)
|
Chris@16
|
474 {
|
Chris@16
|
475 return buffers_iterator<BufferSequence>::end(buffers);
|
Chris@16
|
476 }
|
Chris@16
|
477
|
Chris@16
|
478 } // namespace asio
|
Chris@16
|
479 } // namespace boost
|
Chris@16
|
480
|
Chris@16
|
481 #include <boost/asio/detail/pop_options.hpp>
|
Chris@16
|
482
|
Chris@16
|
483 #endif // BOOST_ASIO_BUFFERS_ITERATOR_HPP
|