Clementine
buffers_iterator.hpp
1 //
2 // buffers_iterator.hpp
3 // ~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2020 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 ASIO_BUFFERS_ITERATOR_HPP
12 #define 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 "asio/detail/config.hpp"
19 #include <cstddef>
20 #include <iterator>
21 #include "asio/buffer.hpp"
22 #include "asio/detail/assert.hpp"
23 #include "asio/detail/type_traits.hpp"
24 
25 #include "asio/detail/push_options.hpp"
26 
27 namespace asio {
28 
29 namespace detail
30 {
31  template <bool IsMutable>
33 
34  template <>
36  {
37  typedef const_buffer buffer_type;
38  template <typename ByteType>
39  struct byte_type
40  {
41  typedef typename add_const<ByteType>::type type;
42  };
43  };
44 
45  template <>
47  {
49  template <typename ByteType>
50  struct byte_type
51  {
52  typedef ByteType type;
53  };
54  };
55 
56  template <typename BufferSequence, typename ByteType>
58  {
59  enum
60  {
61  is_mutable = is_convertible<
62  typename BufferSequence::value_type,
63  mutable_buffer>::value
64  };
66  typedef typename helper::buffer_type buffer_type;
67  typedef typename helper::template byte_type<ByteType>::type byte_type;
68  typedef typename BufferSequence::const_iterator const_iterator;
69  };
70 
71  template <typename ByteType>
73  {
75  typedef ByteType byte_type;
76  typedef const mutable_buffer* const_iterator;
77  };
78 
79  template <typename ByteType>
81  {
82  typedef const_buffer buffer_type;
83  typedef typename add_const<ByteType>::type byte_type;
84  typedef const const_buffer* const_iterator;
85  };
86 
87 #if !defined(ASIO_NO_DEPRECATED)
88 
89  template <typename ByteType>
91  {
93  typedef ByteType byte_type;
94  typedef const mutable_buffer* const_iterator;
95  };
96 
97  template <typename ByteType>
99  {
100  typedef const_buffer buffer_type;
101  typedef typename add_const<ByteType>::type byte_type;
102  typedef const const_buffer* const_iterator;
103  };
104 
105 #endif // !defined(ASIO_NO_DEPRECATED)
106 }
107 
109 template <typename BufferSequence, typename ByteType = char>
111 {
112 private:
113  typedef typename detail::buffers_iterator_types<
114  BufferSequence, ByteType>::buffer_type buffer_type;
115 
116  typedef typename detail::buffers_iterator_types<BufferSequence,
117  ByteType>::const_iterator buffer_sequence_iterator_type;
118 
119 public:
121  typedef std::ptrdiff_t difference_type;
122 
124  typedef ByteType value_type;
125 
126 #if defined(GENERATING_DOCUMENTATION)
127 
133  typedef const_or_non_const_ByteType* pointer;
134 #else // defined(GENERATING_DOCUMENTATION)
135  typedef typename detail::buffers_iterator_types<
136  BufferSequence, ByteType>::byte_type* pointer;
137 #endif // defined(GENERATING_DOCUMENTATION)
138 
139 #if defined(GENERATING_DOCUMENTATION)
140 
146  typedef const_or_non_const_ByteType& reference;
147 #else // defined(GENERATING_DOCUMENTATION)
148  typedef typename detail::buffers_iterator_types<
149  BufferSequence, ByteType>::byte_type& reference;
150 #endif // defined(GENERATING_DOCUMENTATION)
151 
153  typedef std::random_access_iterator_tag iterator_category;
154 
157  : current_buffer_(),
158  current_buffer_position_(0),
159  begin_(),
160  current_(),
161  end_(),
162  position_(0)
163  {
164  }
165 
167  static buffers_iterator begin(const BufferSequence& buffers)
168 #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
169  __attribute__ ((__noinline__))
170 #endif // defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
171  {
172  buffers_iterator new_iter;
173  new_iter.begin_ = asio::buffer_sequence_begin(buffers);
174  new_iter.current_ = asio::buffer_sequence_begin(buffers);
175  new_iter.end_ = asio::buffer_sequence_end(buffers);
176  while (new_iter.current_ != new_iter.end_)
177  {
178  new_iter.current_buffer_ = *new_iter.current_;
179  if (new_iter.current_buffer_.size() > 0)
180  break;
181  ++new_iter.current_;
182  }
183  return new_iter;
184  }
185 
187  static buffers_iterator end(const BufferSequence& buffers)
188 #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
189  __attribute__ ((__noinline__))
190 #endif // defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
191  {
192  buffers_iterator new_iter;
193  new_iter.begin_ = asio::buffer_sequence_begin(buffers);
194  new_iter.current_ = asio::buffer_sequence_begin(buffers);
195  new_iter.end_ = asio::buffer_sequence_end(buffers);
196  while (new_iter.current_ != new_iter.end_)
197  {
198  buffer_type buffer = *new_iter.current_;
199  new_iter.position_ += buffer.size();
200  ++new_iter.current_;
201  }
202  return new_iter;
203  }
204 
206  reference operator*() const
207  {
208  return dereference();
209  }
210 
212  pointer operator->() const
213  {
214  return &dereference();
215  }
216 
218  reference operator[](std::ptrdiff_t difference) const
219  {
220  buffers_iterator tmp(*this);
221  tmp.advance(difference);
222  return *tmp;
223  }
224 
227  {
228  increment();
229  return *this;
230  }
231 
234  {
235  buffers_iterator tmp(*this);
236  ++*this;
237  return tmp;
238  }
239 
242  {
243  decrement();
244  return *this;
245  }
246 
249  {
250  buffers_iterator tmp(*this);
251  --*this;
252  return tmp;
253  }
254 
256  buffers_iterator& operator+=(std::ptrdiff_t difference)
257  {
258  advance(difference);
259  return *this;
260  }
261 
263  buffers_iterator& operator-=(std::ptrdiff_t difference)
264  {
265  advance(-difference);
266  return *this;
267  }
268 
271  std::ptrdiff_t difference)
272  {
273  buffers_iterator tmp(iter);
274  tmp.advance(difference);
275  return tmp;
276  }
277 
279  friend buffers_iterator operator+(std::ptrdiff_t difference,
280  const buffers_iterator& iter)
281  {
282  buffers_iterator tmp(iter);
283  tmp.advance(difference);
284  return tmp;
285  }
286 
289  std::ptrdiff_t difference)
290  {
291  buffers_iterator tmp(iter);
292  tmp.advance(-difference);
293  return tmp;
294  }
295 
297  friend std::ptrdiff_t operator-(const buffers_iterator& a,
298  const buffers_iterator& b)
299  {
300  return b.distance_to(a);
301  }
302 
304  friend bool operator==(const buffers_iterator& a, const buffers_iterator& b)
305  {
306  return a.equal(b);
307  }
308 
310  friend bool operator!=(const buffers_iterator& a, const buffers_iterator& b)
311  {
312  return !a.equal(b);
313  }
314 
316  friend bool operator<(const buffers_iterator& a, const buffers_iterator& b)
317  {
318  return a.distance_to(b) > 0;
319  }
320 
322  friend bool operator<=(const buffers_iterator& a, const buffers_iterator& b)
323  {
324  return !(b < a);
325  }
326 
328  friend bool operator>(const buffers_iterator& a, const buffers_iterator& b)
329  {
330  return b < a;
331  }
332 
334  friend bool operator>=(const buffers_iterator& a, const buffers_iterator& b)
335  {
336  return !(a < b);
337  }
338 
339 private:
340  // Dereference the iterator.
341  reference dereference() const
342  {
343  return static_cast<pointer>(
344  current_buffer_.data())[current_buffer_position_];
345  }
346 
347  // Compare two iterators for equality.
348  bool equal(const buffers_iterator& other) const
349  {
350  return position_ == other.position_;
351  }
352 
353  // Increment the iterator.
354  void increment()
355  {
356  ASIO_ASSERT(current_ != end_ && "iterator out of bounds");
357  ++position_;
358 
359  // Check if the increment can be satisfied by the current buffer.
360  ++current_buffer_position_;
361  if (current_buffer_position_ != current_buffer_.size())
362  return;
363 
364  // Find the next non-empty buffer.
365  ++current_;
366  current_buffer_position_ = 0;
367  while (current_ != end_)
368  {
369  current_buffer_ = *current_;
370  if (current_buffer_.size() > 0)
371  return;
372  ++current_;
373  }
374  }
375 
376  // Decrement the iterator.
377  void decrement()
378  {
379  ASIO_ASSERT(position_ > 0 && "iterator out of bounds");
380  --position_;
381 
382  // Check if the decrement can be satisfied by the current buffer.
383  if (current_buffer_position_ != 0)
384  {
385  --current_buffer_position_;
386  return;
387  }
388 
389  // Find the previous non-empty buffer.
390  buffer_sequence_iterator_type iter = current_;
391  while (iter != begin_)
392  {
393  --iter;
394  buffer_type buffer = *iter;
395  std::size_t buffer_size = buffer.size();
396  if (buffer_size > 0)
397  {
398  current_ = iter;
399  current_buffer_ = buffer;
400  current_buffer_position_ = buffer_size - 1;
401  return;
402  }
403  }
404  }
405 
406  // Advance the iterator by the specified distance.
407  void advance(std::ptrdiff_t n)
408  {
409  if (n > 0)
410  {
411  ASIO_ASSERT(current_ != end_ && "iterator out of bounds");
412  for (;;)
413  {
414  std::ptrdiff_t current_buffer_balance
415  = current_buffer_.size() - current_buffer_position_;
416 
417  // Check if the advance can be satisfied by the current buffer.
418  if (current_buffer_balance > n)
419  {
420  position_ += n;
421  current_buffer_position_ += n;
422  return;
423  }
424 
425  // Update position.
426  n -= current_buffer_balance;
427  position_ += current_buffer_balance;
428 
429  // Move to next buffer. If it is empty then it will be skipped on the
430  // next iteration of this loop.
431  if (++current_ == end_)
432  {
433  ASIO_ASSERT(n == 0 && "iterator out of bounds");
434  current_buffer_ = buffer_type();
435  current_buffer_position_ = 0;
436  return;
437  }
438  current_buffer_ = *current_;
439  current_buffer_position_ = 0;
440  }
441  }
442  else if (n < 0)
443  {
444  std::size_t abs_n = -n;
445  ASIO_ASSERT(position_ >= abs_n && "iterator out of bounds");
446  for (;;)
447  {
448  // Check if the advance can be satisfied by the current buffer.
449  if (current_buffer_position_ >= abs_n)
450  {
451  position_ -= abs_n;
452  current_buffer_position_ -= abs_n;
453  return;
454  }
455 
456  // Update position.
457  abs_n -= current_buffer_position_;
458  position_ -= current_buffer_position_;
459 
460  // Check if we've reached the beginning of the buffers.
461  if (current_ == begin_)
462  {
463  ASIO_ASSERT(abs_n == 0 && "iterator out of bounds");
464  current_buffer_position_ = 0;
465  return;
466  }
467 
468  // Find the previous non-empty buffer.
469  buffer_sequence_iterator_type iter = current_;
470  while (iter != begin_)
471  {
472  --iter;
473  buffer_type buffer = *iter;
474  std::size_t buffer_size = buffer.size();
475  if (buffer_size > 0)
476  {
477  current_ = iter;
478  current_buffer_ = buffer;
479  current_buffer_position_ = buffer_size;
480  break;
481  }
482  }
483  }
484  }
485  }
486 
487  // Determine the distance between two iterators.
488  std::ptrdiff_t distance_to(const buffers_iterator& other) const
489  {
490  return other.position_ - position_;
491  }
492 
493  buffer_type current_buffer_;
494  std::size_t current_buffer_position_;
495  buffer_sequence_iterator_type begin_;
496  buffer_sequence_iterator_type current_;
497  buffer_sequence_iterator_type end_;
498  std::size_t position_;
499 };
500 
502 template <typename BufferSequence>
503 inline buffers_iterator<BufferSequence> buffers_begin(
504  const BufferSequence& buffers)
505 {
507 }
508 
510 template <typename BufferSequence>
511 inline buffers_iterator<BufferSequence> buffers_end(
512  const BufferSequence& buffers)
513 {
515 }
516 
517 } // namespace asio
518 
519 #include "asio/detail/pop_options.hpp"
520 
521 #endif // ASIO_BUFFERS_ITERATOR_HPP
buffers_iterator & operator+=(std::ptrdiff_t difference)
Addition operator.
Definition: buffers_iterator.hpp:256
reference operator[](std::ptrdiff_t difference) const
Access an individual element.
Definition: buffers_iterator.hpp:218
buffers_iterator & operator-=(std::ptrdiff_t difference)
Subtraction operator.
Definition: buffers_iterator.hpp:263
Holds a buffer that cannot be modified.
Definition: buffer.hpp:226
friend bool operator>=(const buffers_iterator &a, const buffers_iterator &b)
Compare two iterators.
Definition: buffers_iterator.hpp:334
A random access iterator over the bytes in a buffer sequence.
Definition: buffers_iterator.hpp:110
friend bool operator!=(const buffers_iterator &a, const buffers_iterator &b)
Test two iterators for inequality.
Definition: buffers_iterator.hpp:310
buffers_iterator operator--(int)
Decrement operator (postfix).
Definition: buffers_iterator.hpp:248
friend std::ptrdiff_t operator-(const buffers_iterator &a, const buffers_iterator &b)
Subtraction operator.
Definition: buffers_iterator.hpp:297
friend bool operator>(const buffers_iterator &a, const buffers_iterator &b)
Compare two iterators.
Definition: buffers_iterator.hpp:328
friend buffers_iterator operator-(const buffers_iterator &iter, std::ptrdiff_t difference)
Subtraction operator.
Definition: buffers_iterator.hpp:288
buffers_iterator & operator++()
Increment operator (prefix).
Definition: buffers_iterator.hpp:226
(Deprecated: Use const_buffer.) Adapts a single non-modifiable buffer so that it meets the requiremen...
Definition: buffer.hpp:306
Definition: chrono.h:284
ASIO_MUTABLE_BUFFER buffer(const mutable_buffer &b) ASIO_NOEXCEPT
Create a new modifiable buffer from an existing buffer.
Definition: buffer.hpp:909
static buffers_iterator end(const BufferSequence &buffers)
Construct an iterator representing the end of the buffers&#39; data.
Definition: buffers_iterator.hpp:187
Definition: buffers_iterator.hpp:57
friend bool operator==(const buffers_iterator &a, const buffers_iterator &b)
Test two iterators for equality.
Definition: buffers_iterator.hpp:304
friend bool operator<=(const buffers_iterator &a, const buffers_iterator &b)
Compare two iterators.
Definition: buffers_iterator.hpp:322
buffers_iterator operator++(int)
Increment operator (postfix).
Definition: buffers_iterator.hpp:233
Holds a buffer that can be modified.
Definition: buffer.hpp:92
Definition: buffers_iterator.hpp:32
reference operator*() const
Dereference an iterator.
Definition: buffers_iterator.hpp:206
buffers_iterator()
Default constructor. Creates an iterator in an undefined state.
Definition: buffers_iterator.hpp:156
std::ptrdiff_t difference_type
The type used for the distance between two iterators.
Definition: buffers_iterator.hpp:121
ByteType value_type
The type of the value pointed to by the iterator.
Definition: buffers_iterator.hpp:124
friend buffers_iterator operator+(std::ptrdiff_t difference, const buffers_iterator &iter)
Addition operator.
Definition: buffers_iterator.hpp:279
const mutable_buffer * buffer_sequence_begin(const MutableBuffer &b, typename enable_if< is_convertible< const MutableBuffer *, const mutable_buffer *>::value >::type *=0) ASIO_NOEXCEPT
Get an iterator to the first element in a buffer sequence.
Definition: buffer.hpp:388
const mutable_buffer * buffer_sequence_end(const MutableBuffer &b, typename enable_if< is_convertible< const MutableBuffer *, const mutable_buffer *>::value >::type *=0) ASIO_NOEXCEPT
Get an iterator to one past the end element in a buffer sequence.
Definition: buffer.hpp:465
std::random_access_iterator_tag iterator_category
The iterator category.
Definition: buffers_iterator.hpp:153
friend bool operator<(const buffers_iterator &a, const buffers_iterator &b)
Compare two iterators.
Definition: buffers_iterator.hpp:316
static buffers_iterator begin(const BufferSequence &buffers)
Construct an iterator representing the beginning of the buffers&#39; data.
Definition: buffers_iterator.hpp:167
friend buffers_iterator operator+(const buffers_iterator &iter, std::ptrdiff_t difference)
Addition operator.
Definition: buffers_iterator.hpp:270
Definition: any_io_executor.hpp:28
(Deprecated: Use mutable_buffer.) Adapts a single modifiable buffer so that it meets the requirements...
Definition: buffer.hpp:162
buffers_iterator & operator--()
Decrement operator (prefix).
Definition: buffers_iterator.hpp:241
pointer operator->() const
Dereference an iterator.
Definition: buffers_iterator.hpp:212