consuming_buffers.hpp
Go to the documentation of this file.
00001 //
00002 // consuming_buffers.hpp
00003 // ~~~~~~~~~~~~~~~~~~~~~
00004 //
00005 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
00006 //
00007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
00008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
00009 //
00010 
00011 #ifndef ASIO_DETAIL_CONSUMING_BUFFERS_HPP
00012 #define ASIO_DETAIL_CONSUMING_BUFFERS_HPP
00013 
00014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00015 # pragma once
00016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
00017 
00018 #include "asio/detail/push_options.hpp"
00019 
00020 #include "asio/detail/push_options.hpp"
00021 #include <algorithm>
00022 #include <cstddef>
00023 #include <boost/config.hpp>
00024 #include <boost/iterator/iterator_facade.hpp>
00025 #include "asio/detail/pop_options.hpp"
00026 
00027 #include "asio/buffer.hpp"
00028 
00029 namespace asio {
00030 namespace detail {
00031 
00032 // A proxy iterator for a sub-range in a list of buffers.
00033 template <typename Buffer, typename Buffer_Iterator>
00034 class consuming_buffers_iterator
00035   : public boost::iterator_facade<
00036         consuming_buffers_iterator<Buffer, Buffer_Iterator>,
00037         const Buffer, boost::forward_traversal_tag>
00038 {
00039 public:
00040   // Default constructor creates an end iterator.
00041   consuming_buffers_iterator()
00042     : at_end_(true)
00043   {
00044   }
00045 
00046   // Construct with a buffer for the first entry and an iterator
00047   // range for the remaining entries.
00048   consuming_buffers_iterator(bool at_end, const Buffer& first,
00049       Buffer_Iterator begin_remainder, Buffer_Iterator end_remainder)
00050     : at_end_(at_end),
00051       first_(buffer(first, max_size)),
00052       begin_remainder_(begin_remainder),
00053       end_remainder_(end_remainder),
00054       offset_(0)
00055   {
00056   }
00057 
00058 private:
00059   friend class boost::iterator_core_access;
00060 
00061   enum { max_size = 65536 };
00062 
00063   void increment()
00064   {
00065     if (!at_end_)
00066     {
00067       if (begin_remainder_ == end_remainder_
00068           || offset_ + buffer_size(first_) >= max_size)
00069       {
00070         at_end_ = true;
00071       }
00072       else
00073       {
00074         offset_ += buffer_size(first_);
00075         first_ = buffer(*begin_remainder_++, max_size - offset_);
00076       }
00077     }
00078   }
00079 
00080   bool equal(const consuming_buffers_iterator& other) const
00081   {
00082     if (at_end_ && other.at_end_)
00083       return true;
00084     return !at_end_ && !other.at_end_
00085       && buffer_cast<const void*>(first_)
00086         == buffer_cast<const void*>(other.first_)
00087       && buffer_size(first_) == buffer_size(other.first_)
00088       && begin_remainder_ == other.begin_remainder_
00089       && end_remainder_ == other.end_remainder_;
00090   }
00091 
00092   const Buffer& dereference() const
00093   {
00094     return first_;
00095   }
00096 
00097   bool at_end_;
00098   Buffer first_;
00099   Buffer_Iterator begin_remainder_;
00100   Buffer_Iterator end_remainder_;
00101   std::size_t offset_;
00102 };
00103 
00104 // A proxy for a sub-range in a list of buffers.
00105 template <typename Buffer, typename Buffers>
00106 class consuming_buffers
00107 {
00108 public:
00109   // The type for each element in the list of buffers.
00110   typedef Buffer value_type;
00111 
00112   // A forward-only iterator type that may be used to read elements.
00113   typedef consuming_buffers_iterator<Buffer, typename Buffers::const_iterator>
00114     const_iterator;
00115 
00116   // Construct to represent the entire list of buffers.
00117   consuming_buffers(const Buffers& buffers)
00118     : buffers_(buffers),
00119       at_end_(buffers_.begin() == buffers_.end()),
00120       first_(*buffers_.begin()),
00121       begin_remainder_(buffers_.begin())
00122   {
00123     if (!at_end_)
00124       ++begin_remainder_;
00125   }
00126 
00127   // Copy constructor.
00128   consuming_buffers(const consuming_buffers& other)
00129     : buffers_(other.buffers_),
00130       at_end_(other.at_end_),
00131       first_(other.first_),
00132       begin_remainder_(buffers_.begin())
00133   {
00134     typename Buffers::const_iterator first = other.buffers_.begin();
00135     typename Buffers::const_iterator second = other.begin_remainder_;
00136     std::advance(begin_remainder_, std::distance(first, second));
00137   }
00138 
00139   // Assignment operator.
00140   consuming_buffers& operator=(const consuming_buffers& other)
00141   {
00142     buffers_ = other.buffers_;
00143     at_end_ = other.at_end_;
00144     first_ = other.first_;
00145     begin_remainder_ = buffers_.begin();
00146     typename Buffers::const_iterator first = other.buffers_.begin();
00147     typename Buffers::const_iterator second = other.begin_remainder_;
00148     std::advance(begin_remainder_, std::distance(first, second));
00149     return *this;
00150   }
00151 
00152   // Get a forward-only iterator to the first element.
00153   const_iterator begin() const
00154   {
00155     return const_iterator(at_end_, first_, begin_remainder_, buffers_.end());
00156   }
00157 
00158   // Get a forward-only iterator for one past the last element.
00159   const_iterator end() const
00160   {
00161     return const_iterator();
00162   }
00163 
00164   // Consume the specified number of bytes from the buffers.
00165   void consume(std::size_t size)
00166   {
00167     // Remove buffers from the start until the specified size is reached.
00168     while (size > 0 && !at_end_)
00169     {
00170       if (buffer_size(first_) <= size)
00171       {
00172         size -= buffer_size(first_);
00173         if (begin_remainder_ == buffers_.end())
00174           at_end_ = true;
00175         else
00176           first_ = *begin_remainder_++;
00177       }
00178       else
00179       {
00180         first_ = first_ + size;
00181         size = 0;
00182       }
00183     }
00184 
00185     // Remove any more empty buffers at the start.
00186     while (!at_end_ && buffer_size(first_) == 0)
00187     {
00188       if (begin_remainder_ == buffers_.end())
00189         at_end_ = true;
00190       else
00191         first_ = *begin_remainder_++;
00192     }
00193   }
00194 
00195 private:
00196   Buffers buffers_;
00197   bool at_end_;
00198   Buffer first_;
00199   typename Buffers::const_iterator begin_remainder_;
00200 };
00201 
00202 // Specialisation for null_buffers to ensure that the null_buffers type is
00203 // always passed through to the underlying read or write operation.
00204 template <typename Buffer>
00205 class consuming_buffers<Buffer, asio::null_buffers>
00206   : public asio::null_buffers
00207 {
00208 public:
00209   consuming_buffers(const asio::null_buffers&)
00210   {
00211     // No-op.
00212   }
00213 
00214   void consume(std::size_t)
00215   {
00216     // No-op.
00217   }
00218 };
00219 
00220 } // namespace detail
00221 } // namespace asio
00222 
00223 #include "asio/detail/pop_options.hpp"
00224 
00225 #endif // ASIO_DETAIL_CONSUMING_BUFFERS_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


Castor
Author(s): Carpe Noctem
autogenerated on Fri Nov 8 2013 11:05:39