PageRenderTime 34ms CodeModel.GetById 18ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/asio/detail/consuming_buffers.hpp

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