Statistics
| Revision:

root / tmp / org.txm.statsengine.r.core.win32 / res / win32 / library / BH / include / boost / asio / detail / consuming_buffers.hpp @ 2486

History | View | Annotate | Download (7.3 kB)

1
//
2
// detail/consuming_buffers.hpp
3
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
//
5
// Copyright (c) 2003-2015 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 <iterator>
21
#include <boost/asio/buffer.hpp>
22
#include <boost/asio/detail/limits.hpp>
23

    
24
#include <boost/asio/detail/push_options.hpp>
25

    
26
namespace boost {
27
namespace asio {
28
namespace detail {
29

    
30
// A proxy iterator for a sub-range in a list of buffers.
31
template <typename Buffer, typename Buffer_Iterator>
32
class consuming_buffers_iterator
33
{
34
public:
35
  /// The type used for the distance between two iterators.
36
  typedef std::ptrdiff_t difference_type;
37

    
38
  /// The type of the value pointed to by the iterator.
39
  typedef Buffer value_type;
40

    
41
  /// The type of the result of applying operator->() to the iterator.
42
  typedef const Buffer* pointer;
43

    
44
  /// The type of the result of applying operator*() to the iterator.
45
  typedef const Buffer& reference;
46

    
47
  /// The iterator category.
48
  typedef std::forward_iterator_tag iterator_category;
49

    
50
  // Default constructor creates an end iterator.
51
  consuming_buffers_iterator()
52
    : at_end_(true)
53
  {
54
  }
55

    
56
  // Construct with a buffer for the first entry and an iterator
57
  // range for the remaining entries.
58
  consuming_buffers_iterator(bool at_end, const Buffer& first,
59
      Buffer_Iterator begin_remainder, Buffer_Iterator end_remainder,
60
      std::size_t max_size)
61
    : at_end_(max_size > 0 ? at_end : true),
62
      first_(buffer(first, max_size)),
63
      begin_remainder_(begin_remainder),
64
      end_remainder_(end_remainder),
65
      offset_(0),
66
      max_size_(max_size)
67
  {
68
  }
69

    
70
  // Dereference an iterator.
71
  const Buffer& operator*() const
72
  {
73
    return dereference();
74
  }
75

    
76
  // Dereference an iterator.
77
  const Buffer* operator->() const
78
  {
79
    return &dereference();
80
  }
81

    
82
  // Increment operator (prefix).
83
  consuming_buffers_iterator& operator++()
84
  {
85
    increment();
86
    return *this;
87
  }
88

    
89
  // Increment operator (postfix).
90
  consuming_buffers_iterator operator++(int)
91
  {
92
    consuming_buffers_iterator tmp(*this);
93
    ++*this;
94
    return tmp;
95
  }
96

    
97
  // Test two iterators for equality.
98
  friend bool operator==(const consuming_buffers_iterator& a,
99
      const consuming_buffers_iterator& b)
100
  {
101
    return a.equal(b);
102
  }
103

    
104
  // Test two iterators for inequality.
105
  friend bool operator!=(const consuming_buffers_iterator& a,
106
      const consuming_buffers_iterator& b)
107
  {
108
    return !a.equal(b);
109
  }
110

    
111
private:
112
  void increment()
113
  {
114
    if (!at_end_)
115
    {
116
      if (begin_remainder_ == end_remainder_
117
          || offset_ + buffer_size(first_) >= max_size_)
118
      {
119
        at_end_ = true;
120
      }
121
      else
122
      {
123
        offset_ += buffer_size(first_);
124
        first_ = buffer(*begin_remainder_++, max_size_ - offset_);
125
      }
126
    }
127
  }
128

    
129
  bool equal(const consuming_buffers_iterator& other) const
130
  {
131
    if (at_end_ && other.at_end_)
132
      return true;
133
    return !at_end_ && !other.at_end_
134
      && buffer_cast<const void*>(first_)
135
        == buffer_cast<const void*>(other.first_)
136
      && buffer_size(first_) == buffer_size(other.first_)
137
      && begin_remainder_ == other.begin_remainder_
138
      && end_remainder_ == other.end_remainder_;
139
  }
140

    
141
  const Buffer& dereference() const
142
  {
143
    return first_;
144
  }
145

    
146
  bool at_end_;
147
  Buffer first_;
148
  Buffer_Iterator begin_remainder_;
149
  Buffer_Iterator end_remainder_;
150
  std::size_t offset_;
151
  std::size_t max_size_;
152
};
153

    
154
// A proxy for a sub-range in a list of buffers.
155
template <typename Buffer, typename Buffers>
156
class consuming_buffers
157
{
158
public:
159
  // The type for each element in the list of buffers.
160
  typedef Buffer value_type;
161

    
162
  // A forward-only iterator type that may be used to read elements.
163
  typedef consuming_buffers_iterator<Buffer, typename Buffers::const_iterator>
164
    const_iterator;
165

    
166
  // Construct to represent the entire list of buffers.
167
  consuming_buffers(const Buffers& buffers)
168
    : buffers_(buffers),
169
      at_end_(buffers_.begin() == buffers_.end()),
170
      begin_remainder_(buffers_.begin()),
171
      max_size_((std::numeric_limits<std::size_t>::max)())
172
  {
173
    if (!at_end_)
174
    {
175
      first_ = *buffers_.begin();
176
      ++begin_remainder_;
177
    }
178
  }
179

    
180
  // Copy constructor.
181
  consuming_buffers(const consuming_buffers& other)
182
    : buffers_(other.buffers_),
183
      at_end_(other.at_end_),
184
      first_(other.first_),
185
      begin_remainder_(buffers_.begin()),
186
      max_size_(other.max_size_)
187
  {
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
  }
192

    
193
  // Assignment operator.
194
  consuming_buffers& operator=(const consuming_buffers& other)
195
  {
196
    buffers_ = other.buffers_;
197
    at_end_ = other.at_end_;
198
    first_ = other.first_;
199
    begin_remainder_ = buffers_.begin();
200
    typename Buffers::const_iterator first = other.buffers_.begin();
201
    typename Buffers::const_iterator second = other.begin_remainder_;
202
    std::advance(begin_remainder_, std::distance(first, second));
203
    max_size_ = other.max_size_;
204
    return *this;
205
  }
206

    
207
  // Get a forward-only iterator to the first element.
208
  const_iterator begin() const
209
  {
210
    return const_iterator(at_end_, first_,
211
        begin_remainder_, buffers_.end(), max_size_);
212
  }
213

    
214
  // Get a forward-only iterator for one past the last element.
215
  const_iterator end() const
216
  {
217
    return const_iterator();
218
  }
219

    
220
  // Set the maximum size for a single transfer.
221
  void prepare(std::size_t max_size)
222
  {
223
    max_size_ = max_size;
224
  }
225

    
226
  // Consume the specified number of bytes from the buffers.
227
  void consume(std::size_t size)
228
  {
229
    // Remove buffers from the start until the specified size is reached.
230
    while (size > 0 && !at_end_)
231
    {
232
      if (buffer_size(first_) <= size)
233
      {
234
        size -= buffer_size(first_);
235
        if (begin_remainder_ == buffers_.end())
236
          at_end_ = true;
237
        else
238
          first_ = *begin_remainder_++;
239
      }
240
      else
241
      {
242
        first_ = first_ + size;
243
        size = 0;
244
      }
245
    }
246

    
247
    // Remove any more empty buffers at the start.
248
    while (!at_end_ && buffer_size(first_) == 0)
249
    {
250
      if (begin_remainder_ == buffers_.end())
251
        at_end_ = true;
252
      else
253
        first_ = *begin_remainder_++;
254
    }
255
  }
256

    
257
private:
258
  Buffers buffers_;
259
  bool at_end_;
260
  Buffer first_;
261
  typename Buffers::const_iterator begin_remainder_;
262
  std::size_t max_size_;
263
};
264

    
265
// Specialisation for null_buffers to ensure that the null_buffers type is
266
// always passed through to the underlying read or write operation.
267
template <typename Buffer>
268
class consuming_buffers<Buffer, boost::asio::null_buffers>
269
  : public boost::asio::null_buffers
270
{
271
public:
272
  consuming_buffers(const boost::asio::null_buffers&)
273
  {
274
    // No-op.
275
  }
276

    
277
  void prepare(std::size_t)
278
  {
279
    // No-op.
280
  }
281

    
282
  void consume(std::size_t)
283
  {
284
    // No-op.
285
  }
286
};
287

    
288
} // namespace detail
289
} // namespace asio
290
} // namespace boost
291

    
292
#include <boost/asio/detail/pop_options.hpp>
293

    
294
#endif // BOOST_ASIO_DETAIL_CONSUMING_BUFFERS_HPP