|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521 |
- //
- // buffers_iterator.hpp
- // ~~~~~~~~~~~~~~~~~~~~
- //
- // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
- //
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- //
-
- #ifndef ASIO_BUFFERS_ITERATOR_HPP
- #define ASIO_BUFFERS_ITERATOR_HPP
-
- #if defined(_MSC_VER) && (_MSC_VER >= 1200)
- # pragma once
- #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
- #include "asio/detail/config.hpp"
- #include <cstddef>
- #include <iterator>
- #include "asio/buffer.hpp"
- #include "asio/detail/assert.hpp"
- #include "asio/detail/type_traits.hpp"
-
- #include "asio/detail/push_options.hpp"
-
- namespace asio {
-
- namespace detail
- {
- template <bool IsMutable>
- struct buffers_iterator_types_helper;
-
- template <>
- struct buffers_iterator_types_helper<false>
- {
- typedef const_buffer buffer_type;
- template <typename ByteType>
- struct byte_type
- {
- typedef typename add_const<ByteType>::type type;
- };
- };
-
- template <>
- struct buffers_iterator_types_helper<true>
- {
- typedef mutable_buffer buffer_type;
- template <typename ByteType>
- struct byte_type
- {
- typedef ByteType type;
- };
- };
-
- template <typename BufferSequence, typename ByteType>
- struct buffers_iterator_types
- {
- enum
- {
- is_mutable = is_convertible<
- typename BufferSequence::value_type,
- mutable_buffer>::value
- };
- typedef buffers_iterator_types_helper<is_mutable> helper;
- typedef typename helper::buffer_type buffer_type;
- typedef typename helper::template byte_type<ByteType>::type byte_type;
- typedef typename BufferSequence::const_iterator const_iterator;
- };
-
- template <typename ByteType>
- struct buffers_iterator_types<mutable_buffer, ByteType>
- {
- typedef mutable_buffer buffer_type;
- typedef ByteType byte_type;
- typedef const mutable_buffer* const_iterator;
- };
-
- template <typename ByteType>
- struct buffers_iterator_types<const_buffer, ByteType>
- {
- typedef const_buffer buffer_type;
- typedef typename add_const<ByteType>::type byte_type;
- typedef const const_buffer* const_iterator;
- };
-
- #if !defined(ASIO_NO_DEPRECATED)
-
- template <typename ByteType>
- struct buffers_iterator_types<mutable_buffers_1, ByteType>
- {
- typedef mutable_buffer buffer_type;
- typedef ByteType byte_type;
- typedef const mutable_buffer* const_iterator;
- };
-
- template <typename ByteType>
- struct buffers_iterator_types<const_buffers_1, ByteType>
- {
- typedef const_buffer buffer_type;
- typedef typename add_const<ByteType>::type byte_type;
- typedef const const_buffer* const_iterator;
- };
-
- #endif // !defined(ASIO_NO_DEPRECATED)
- }
-
- /// A random access iterator over the bytes in a buffer sequence.
- template <typename BufferSequence, typename ByteType = char>
- class buffers_iterator
- {
- private:
- typedef typename detail::buffers_iterator_types<
- BufferSequence, ByteType>::buffer_type buffer_type;
-
- typedef typename detail::buffers_iterator_types<BufferSequence,
- ByteType>::const_iterator buffer_sequence_iterator_type;
-
- public:
- /// The type used for the distance between two iterators.
- typedef std::ptrdiff_t difference_type;
-
- /// The type of the value pointed to by the iterator.
- typedef ByteType value_type;
-
- #if defined(GENERATING_DOCUMENTATION)
- /// The type of the result of applying operator->() to the iterator.
- /**
- * If the buffer sequence stores buffer objects that are convertible to
- * mutable_buffer, this is a pointer to a non-const ByteType. Otherwise, a
- * pointer to a const ByteType.
- */
- typedef const_or_non_const_ByteType* pointer;
- #else // defined(GENERATING_DOCUMENTATION)
- typedef typename detail::buffers_iterator_types<
- BufferSequence, ByteType>::byte_type* pointer;
- #endif // defined(GENERATING_DOCUMENTATION)
-
- #if defined(GENERATING_DOCUMENTATION)
- /// The type of the result of applying operator*() to the iterator.
- /**
- * If the buffer sequence stores buffer objects that are convertible to
- * mutable_buffer, this is a reference to a non-const ByteType. Otherwise, a
- * reference to a const ByteType.
- */
- typedef const_or_non_const_ByteType& reference;
- #else // defined(GENERATING_DOCUMENTATION)
- typedef typename detail::buffers_iterator_types<
- BufferSequence, ByteType>::byte_type& reference;
- #endif // defined(GENERATING_DOCUMENTATION)
-
- /// The iterator category.
- typedef std::random_access_iterator_tag iterator_category;
-
- /// Default constructor. Creates an iterator in an undefined state.
- buffers_iterator()
- : current_buffer_(),
- current_buffer_position_(0),
- begin_(),
- current_(),
- end_(),
- position_(0)
- {
- }
-
- /// Construct an iterator representing the beginning of the buffers' data.
- static buffers_iterator begin(const BufferSequence& buffers)
- #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
- __attribute__ ((__noinline__))
- #endif // defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
- {
- buffers_iterator new_iter;
- new_iter.begin_ = asio::buffer_sequence_begin(buffers);
- new_iter.current_ = asio::buffer_sequence_begin(buffers);
- new_iter.end_ = asio::buffer_sequence_end(buffers);
- while (new_iter.current_ != new_iter.end_)
- {
- new_iter.current_buffer_ = *new_iter.current_;
- if (new_iter.current_buffer_.size() > 0)
- break;
- ++new_iter.current_;
- }
- return new_iter;
- }
-
- /// Construct an iterator representing the end of the buffers' data.
- static buffers_iterator end(const BufferSequence& buffers)
- #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
- __attribute__ ((__noinline__))
- #endif // defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
- {
- buffers_iterator new_iter;
- new_iter.begin_ = asio::buffer_sequence_begin(buffers);
- new_iter.current_ = asio::buffer_sequence_begin(buffers);
- new_iter.end_ = asio::buffer_sequence_end(buffers);
- while (new_iter.current_ != new_iter.end_)
- {
- buffer_type buffer = *new_iter.current_;
- new_iter.position_ += buffer.size();
- ++new_iter.current_;
- }
- return new_iter;
- }
-
- /// Dereference an iterator.
- reference operator*() const
- {
- return dereference();
- }
-
- /// Dereference an iterator.
- pointer operator->() const
- {
- return &dereference();
- }
-
- /// Access an individual element.
- reference operator[](std::ptrdiff_t difference) const
- {
- buffers_iterator tmp(*this);
- tmp.advance(difference);
- return *tmp;
- }
-
- /// Increment operator (prefix).
- buffers_iterator& operator++()
- {
- increment();
- return *this;
- }
-
- /// Increment operator (postfix).
- buffers_iterator operator++(int)
- {
- buffers_iterator tmp(*this);
- ++*this;
- return tmp;
- }
-
- /// Decrement operator (prefix).
- buffers_iterator& operator--()
- {
- decrement();
- return *this;
- }
-
- /// Decrement operator (postfix).
- buffers_iterator operator--(int)
- {
- buffers_iterator tmp(*this);
- --*this;
- return tmp;
- }
-
- /// Addition operator.
- buffers_iterator& operator+=(std::ptrdiff_t difference)
- {
- advance(difference);
- return *this;
- }
-
- /// Subtraction operator.
- buffers_iterator& operator-=(std::ptrdiff_t difference)
- {
- advance(-difference);
- return *this;
- }
-
- /// Addition operator.
- friend buffers_iterator operator+(const buffers_iterator& iter,
- std::ptrdiff_t difference)
- {
- buffers_iterator tmp(iter);
- tmp.advance(difference);
- return tmp;
- }
-
- /// Addition operator.
- friend buffers_iterator operator+(std::ptrdiff_t difference,
- const buffers_iterator& iter)
- {
- buffers_iterator tmp(iter);
- tmp.advance(difference);
- return tmp;
- }
-
- /// Subtraction operator.
- friend buffers_iterator operator-(const buffers_iterator& iter,
- std::ptrdiff_t difference)
- {
- buffers_iterator tmp(iter);
- tmp.advance(-difference);
- return tmp;
- }
-
- /// Subtraction operator.
- friend std::ptrdiff_t operator-(const buffers_iterator& a,
- const buffers_iterator& b)
- {
- return b.distance_to(a);
- }
-
- /// Test two iterators for equality.
- friend bool operator==(const buffers_iterator& a, const buffers_iterator& b)
- {
- return a.equal(b);
- }
-
- /// Test two iterators for inequality.
- friend bool operator!=(const buffers_iterator& a, const buffers_iterator& b)
- {
- return !a.equal(b);
- }
-
- /// Compare two iterators.
- friend bool operator<(const buffers_iterator& a, const buffers_iterator& b)
- {
- return a.distance_to(b) > 0;
- }
-
- /// Compare two iterators.
- friend bool operator<=(const buffers_iterator& a, const buffers_iterator& b)
- {
- return !(b < a);
- }
-
- /// Compare two iterators.
- friend bool operator>(const buffers_iterator& a, const buffers_iterator& b)
- {
- return b < a;
- }
-
- /// Compare two iterators.
- friend bool operator>=(const buffers_iterator& a, const buffers_iterator& b)
- {
- return !(a < b);
- }
-
- private:
- // Dereference the iterator.
- reference dereference() const
- {
- return static_cast<pointer>(
- current_buffer_.data())[current_buffer_position_];
- }
-
- // Compare two iterators for equality.
- bool equal(const buffers_iterator& other) const
- {
- return position_ == other.position_;
- }
-
- // Increment the iterator.
- void increment()
- {
- ASIO_ASSERT(current_ != end_ && "iterator out of bounds");
- ++position_;
-
- // Check if the increment can be satisfied by the current buffer.
- ++current_buffer_position_;
- if (current_buffer_position_ != current_buffer_.size())
- return;
-
- // Find the next non-empty buffer.
- ++current_;
- current_buffer_position_ = 0;
- while (current_ != end_)
- {
- current_buffer_ = *current_;
- if (current_buffer_.size() > 0)
- return;
- ++current_;
- }
- }
-
- // Decrement the iterator.
- void decrement()
- {
- ASIO_ASSERT(position_ > 0 && "iterator out of bounds");
- --position_;
-
- // Check if the decrement can be satisfied by the current buffer.
- if (current_buffer_position_ != 0)
- {
- --current_buffer_position_;
- return;
- }
-
- // Find the previous non-empty buffer.
- buffer_sequence_iterator_type iter = current_;
- while (iter != begin_)
- {
- --iter;
- buffer_type buffer = *iter;
- std::size_t buffer_size = buffer.size();
- if (buffer_size > 0)
- {
- current_ = iter;
- current_buffer_ = buffer;
- current_buffer_position_ = buffer_size - 1;
- return;
- }
- }
- }
-
- // Advance the iterator by the specified distance.
- void advance(std::ptrdiff_t n)
- {
- if (n > 0)
- {
- ASIO_ASSERT(current_ != end_ && "iterator out of bounds");
- for (;;)
- {
- std::ptrdiff_t current_buffer_balance
- = current_buffer_.size() - current_buffer_position_;
-
- // Check if the advance can be satisfied by the current buffer.
- if (current_buffer_balance > n)
- {
- position_ += n;
- current_buffer_position_ += n;
- return;
- }
-
- // Update position.
- n -= current_buffer_balance;
- position_ += current_buffer_balance;
-
- // Move to next buffer. If it is empty then it will be skipped on the
- // next iteration of this loop.
- if (++current_ == end_)
- {
- ASIO_ASSERT(n == 0 && "iterator out of bounds");
- current_buffer_ = buffer_type();
- current_buffer_position_ = 0;
- return;
- }
- current_buffer_ = *current_;
- current_buffer_position_ = 0;
- }
- }
- else if (n < 0)
- {
- std::size_t abs_n = -n;
- ASIO_ASSERT(position_ >= abs_n && "iterator out of bounds");
- for (;;)
- {
- // Check if the advance can be satisfied by the current buffer.
- if (current_buffer_position_ >= abs_n)
- {
- position_ -= abs_n;
- current_buffer_position_ -= abs_n;
- return;
- }
-
- // Update position.
- abs_n -= current_buffer_position_;
- position_ -= current_buffer_position_;
-
- // Check if we've reached the beginning of the buffers.
- if (current_ == begin_)
- {
- ASIO_ASSERT(abs_n == 0 && "iterator out of bounds");
- current_buffer_position_ = 0;
- return;
- }
-
- // Find the previous non-empty buffer.
- buffer_sequence_iterator_type iter = current_;
- while (iter != begin_)
- {
- --iter;
- buffer_type buffer = *iter;
- std::size_t buffer_size = buffer.size();
- if (buffer_size > 0)
- {
- current_ = iter;
- current_buffer_ = buffer;
- current_buffer_position_ = buffer_size;
- break;
- }
- }
- }
- }
- }
-
- // Determine the distance between two iterators.
- std::ptrdiff_t distance_to(const buffers_iterator& other) const
- {
- return other.position_ - position_;
- }
-
- buffer_type current_buffer_;
- std::size_t current_buffer_position_;
- buffer_sequence_iterator_type begin_;
- buffer_sequence_iterator_type current_;
- buffer_sequence_iterator_type end_;
- std::size_t position_;
- };
-
- /// Construct an iterator representing the beginning of the buffers' data.
- template <typename BufferSequence>
- inline buffers_iterator<BufferSequence> buffers_begin(
- const BufferSequence& buffers)
- {
- return buffers_iterator<BufferSequence>::begin(buffers);
- }
-
- /// Construct an iterator representing the end of the buffers' data.
- template <typename BufferSequence>
- inline buffers_iterator<BufferSequence> buffers_end(
- const BufferSequence& buffers)
- {
- return buffers_iterator<BufferSequence>::end(buffers);
- }
-
- } // namespace asio
-
- #include "asio/detail/pop_options.hpp"
-
- #endif // ASIO_BUFFERS_ITERATOR_HPP
|