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