PageRenderTime 60ms CodeModel.GetById 10ms app.highlight 45ms RepoModel.GetById 1ms app.codeStats 0ms

/src/contrib/boost/asio/detail/consuming_buffers.hpp

http://pythonocc.googlecode.com/
C++ Header | 282 lines | 211 code | 35 blank | 36 comment | 28 complexity | 4b3b741a1577975919347779842f6df0 MD5 | raw file
  1//
  2// consuming_buffers.hpp
  3// ~~~~~~~~~~~~~~~~~~~~~
  4//
  5// Copyright (c) 2003-2010 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_DETAIL_CONSUMING_BUFFERS_HPP
 12#define BOOST_ASIO_DETAIL_CONSUMING_BUFFERS_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/push_options.hpp>
 19
 20#include <boost/asio/detail/push_options.hpp>
 21#include <algorithm>
 22#include <cstddef>
 23#include <boost/config.hpp>
 24#include <boost/iterator.hpp>
 25#include <boost/limits.hpp>
 26#include <boost/asio/detail/pop_options.hpp>
 27
 28#include <boost/asio/buffer.hpp>
 29
 30namespace boost {
 31namespace asio {
 32namespace detail {
 33
 34// A proxy iterator for a sub-range in a list of buffers.
 35template <typename Buffer, typename Buffer_Iterator>
 36class consuming_buffers_iterator
 37  : public boost::iterator<std::forward_iterator_tag, const Buffer>
 38{
 39public:
 40  // Default constructor creates an end iterator.
 41  consuming_buffers_iterator()
 42    : at_end_(true)
 43  {
 44  }
 45
 46  // Construct with a buffer for the first entry and an iterator
 47  // range for the remaining entries.
 48  consuming_buffers_iterator(bool at_end, const Buffer& first,
 49      Buffer_Iterator begin_remainder, Buffer_Iterator end_remainder,
 50      std::size_t max_size)
 51    : at_end_(max_size > 0 ? at_end : true),
 52      first_(buffer(first, max_size)),
 53      begin_remainder_(begin_remainder),
 54      end_remainder_(end_remainder),
 55      offset_(0),
 56      max_size_(max_size)
 57  {
 58  }
 59
 60  // Dereference an iterator.
 61  const Buffer& operator*() const
 62  {
 63    return dereference();
 64  }
 65
 66  // Dereference an iterator.
 67  const Buffer* operator->() const
 68  {
 69    return &dereference();
 70  }
 71
 72  // Increment operator (prefix).
 73  consuming_buffers_iterator& operator++()
 74  {
 75    increment();
 76    return *this;
 77  }
 78
 79  // Increment operator (postfix).
 80  consuming_buffers_iterator operator++(int)
 81  {
 82    consuming_buffers_iterator tmp(*this);
 83    ++*this;
 84    return tmp;
 85  }
 86
 87  // Test two iterators for equality.
 88  friend bool operator==(const consuming_buffers_iterator& a,
 89      const consuming_buffers_iterator& b)
 90  {
 91    return a.equal(b);
 92  }
 93
 94  // Test two iterators for inequality.
 95  friend bool operator!=(const consuming_buffers_iterator& a,
 96      const consuming_buffers_iterator& b)
 97  {
 98    return !a.equal(b);
 99  }
100
101private:
102  void increment()
103  {
104    if (!at_end_)
105    {
106      if (begin_remainder_ == end_remainder_
107          || offset_ + buffer_size(first_) >= max_size_)
108      {
109        at_end_ = true;
110      }
111      else
112      {
113        offset_ += buffer_size(first_);
114        first_ = buffer(*begin_remainder_++, max_size_ - offset_);
115      }
116    }
117  }
118
119  bool equal(const consuming_buffers_iterator& other) const
120  {
121    if (at_end_ && other.at_end_)
122      return true;
123    return !at_end_ && !other.at_end_
124      && buffer_cast<const void*>(first_)
125        == buffer_cast<const void*>(other.first_)
126      && buffer_size(first_) == buffer_size(other.first_)
127      && begin_remainder_ == other.begin_remainder_
128      && end_remainder_ == other.end_remainder_;
129  }
130
131  const Buffer& dereference() const
132  {
133    return first_;
134  }
135
136  bool at_end_;
137  Buffer first_;
138  Buffer_Iterator begin_remainder_;
139  Buffer_Iterator end_remainder_;
140  std::size_t offset_;
141  std::size_t max_size_;
142};
143
144// A proxy for a sub-range in a list of buffers.
145template <typename Buffer, typename Buffers>
146class consuming_buffers
147{
148public:
149  // The type for each element in the list of buffers.
150  typedef Buffer value_type;
151
152  // A forward-only iterator type that may be used to read elements.
153  typedef consuming_buffers_iterator<Buffer, typename Buffers::const_iterator>
154    const_iterator;
155
156  // Construct to represent the entire list of buffers.
157  consuming_buffers(const Buffers& buffers)
158    : buffers_(buffers),
159      at_end_(buffers_.begin() == buffers_.end()),
160      first_(*buffers_.begin()),
161      begin_remainder_(buffers_.begin()),
162      max_size_((std::numeric_limits<std::size_t>::max)())
163  {
164    if (!at_end_)
165      ++begin_remainder_;
166  }
167
168  // Copy constructor.
169  consuming_buffers(const consuming_buffers& other)
170    : buffers_(other.buffers_),
171      at_end_(other.at_end_),
172      first_(other.first_),
173      begin_remainder_(buffers_.begin()),
174      max_size_(other.max_size_)
175  {
176    typename Buffers::const_iterator first = other.buffers_.begin();
177    typename Buffers::const_iterator second = other.begin_remainder_;
178    std::advance(begin_remainder_, std::distance(first, second));
179  }
180
181  // Assignment operator.
182  consuming_buffers& operator=(const consuming_buffers& other)
183  {
184    buffers_ = other.buffers_;
185    at_end_ = other.at_end_;
186    first_ = other.first_;
187    begin_remainder_ = buffers_.begin();
188    typename Buffers::const_iterator first = other.buffers_.begin();
189    typename Buffers::const_iterator second = other.begin_remainder_;
190    std::advance(begin_remainder_, std::distance(first, second));
191    max_size_ = other.max_size_;
192    return *this;
193  }
194
195  // Get a forward-only iterator to the first element.
196  const_iterator begin() const
197  {
198    return const_iterator(at_end_, first_,
199        begin_remainder_, buffers_.end(), max_size_);
200  }
201
202  // Get a forward-only iterator for one past the last element.
203  const_iterator end() const
204  {
205    return const_iterator();
206  }
207
208  // Set the maximum size for a single transfer.
209  void prepare(std::size_t max_size)
210  {
211    max_size_ = max_size;
212  }
213
214  // Consume the specified number of bytes from the buffers.
215  void consume(std::size_t size)
216  {
217    // Remove buffers from the start until the specified size is reached.
218    while (size > 0 && !at_end_)
219    {
220      if (buffer_size(first_) <= size)
221      {
222        size -= buffer_size(first_);
223        if (begin_remainder_ == buffers_.end())
224          at_end_ = true;
225        else
226          first_ = *begin_remainder_++;
227      }
228      else
229      {
230        first_ = first_ + size;
231        size = 0;
232      }
233    }
234
235    // Remove any more empty buffers at the start.
236    while (!at_end_ && buffer_size(first_) == 0)
237    {
238      if (begin_remainder_ == buffers_.end())
239        at_end_ = true;
240      else
241        first_ = *begin_remainder_++;
242    }
243  }
244
245private:
246  Buffers buffers_;
247  bool at_end_;
248  Buffer first_;
249  typename Buffers::const_iterator begin_remainder_;
250  std::size_t max_size_;
251};
252
253// Specialisation for null_buffers to ensure that the null_buffers type is
254// always passed through to the underlying read or write operation.
255template <typename Buffer>
256class consuming_buffers<Buffer, boost::asio::null_buffers>
257  : public boost::asio::null_buffers
258{
259public:
260  consuming_buffers(const boost::asio::null_buffers&)
261  {
262    // No-op.
263  }
264
265  void prepare(std::size_t)
266  {
267    // No-op.
268  }
269
270  void consume(std::size_t)
271  {
272    // No-op.
273  }
274};
275
276} // namespace detail
277} // namespace asio
278} // namespace boost
279
280#include <boost/asio/detail/pop_options.hpp>
281
282#endif // BOOST_ASIO_DETAIL_CONSUMING_BUFFERS_HPP