diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DEPENDENCIES/generic/include/boost/asio/buffers_iterator.hpp	Tue Aug 05 11:11:38 2014 +0100
@@ -0,0 +1,483 @@
+//
+// buffers_iterator.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2013 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 BOOST_ASIO_BUFFERS_ITERATOR_HPP
+#define BOOST_ASIO_BUFFERS_ITERATOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <cstddef>
+#include <iterator>
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/detail/assert.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+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;
+  };
+}
+
+/// 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;
+
+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_ = buffers.begin();
+    new_iter.current_ = buffers.begin();
+    new_iter.end_ = buffers.end();
+    while (new_iter.current_ != new_iter.end_)
+    {
+      new_iter.current_buffer_ = *new_iter.current_;
+      if (boost::asio::buffer_size(new_iter.current_buffer_) > 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_ = buffers.begin();
+    new_iter.current_ = buffers.begin();
+    new_iter.end_ = buffers.end();
+    while (new_iter.current_ != new_iter.end_)
+    {
+      buffer_type buffer = *new_iter.current_;
+      new_iter.position_ += boost::asio::buffer_size(buffer);
+      ++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 buffer_cast<pointer>(current_buffer_)[current_buffer_position_];
+  }
+
+  // Compare two iterators for equality.
+  bool equal(const buffers_iterator& other) const
+  {
+    return position_ == other.position_;
+  }
+
+  // Increment the iterator.
+  void increment()
+  {
+    BOOST_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_ != boost::asio::buffer_size(current_buffer_))
+      return;
+
+    // Find the next non-empty buffer.
+    ++current_;
+    current_buffer_position_ = 0;
+    while (current_ != end_)
+    {
+      current_buffer_ = *current_;
+      if (boost::asio::buffer_size(current_buffer_) > 0)
+        return;
+      ++current_;
+    }
+  }
+
+  // Decrement the iterator.
+  void decrement()
+  {
+    BOOST_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.
+    typename BufferSequence::const_iterator iter = current_;
+    while (iter != begin_)
+    {
+      --iter;
+      buffer_type buffer = *iter;
+      std::size_t buffer_size = boost::asio::buffer_size(buffer);
+      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)
+    {
+      BOOST_ASIO_ASSERT(current_ != end_ && "iterator out of bounds");
+      for (;;)
+      {
+        std::ptrdiff_t current_buffer_balance
+          = boost::asio::buffer_size(current_buffer_)
+          - 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_)
+        {
+          BOOST_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;
+      BOOST_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_)
+        {
+          BOOST_ASIO_ASSERT(abs_n == 0 && "iterator out of bounds");
+          current_buffer_position_ = 0;
+          return;
+        }
+
+        // Find the previous non-empty buffer.
+        typename BufferSequence::const_iterator iter = current_;
+        while (iter != begin_)
+        {
+          --iter;
+          buffer_type buffer = *iter;
+          std::size_t buffer_size = boost::asio::buffer_size(buffer);
+          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_;
+  typename BufferSequence::const_iterator begin_;
+  typename BufferSequence::const_iterator current_;
+  typename BufferSequence::const_iterator 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
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BUFFERS_ITERATOR_HPP