]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/asio/detail/consuming_buffers.hpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / boost / boost / asio / detail / consuming_buffers.hpp
1 //
2 // detail/consuming_buffers.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2020 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/asio/buffer.hpp>
21 #include <boost/asio/detail/buffer_sequence_adapter.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 // Helper template to determine the maximum number of prepared buffers.
31 template <typename Buffers>
32 struct prepared_buffers_max
33 {
34 enum { value = buffer_sequence_adapter_base::max_buffers };
35 };
36
37 template <typename Elem, std::size_t N>
38 struct prepared_buffers_max<boost::array<Elem, N> >
39 {
40 enum { value = N };
41 };
42
43 #if defined(BOOST_ASIO_HAS_STD_ARRAY)
44
45 template <typename Elem, std::size_t N>
46 struct prepared_buffers_max<std::array<Elem, N> >
47 {
48 enum { value = N };
49 };
50
51 #endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
52
53 // A buffer sequence used to represent a subsequence of the buffers.
54 template <typename Buffer, std::size_t MaxBuffers>
55 struct prepared_buffers
56 {
57 typedef Buffer value_type;
58 typedef const Buffer* const_iterator;
59
60 enum { max_buffers = MaxBuffers < 16 ? MaxBuffers : 16 };
61
62 prepared_buffers() : count(0) {}
63 const_iterator begin() const { return elems; }
64 const_iterator end() const { return elems + count; }
65
66 Buffer elems[max_buffers];
67 std::size_t count;
68 };
69
70 // A proxy for a sub-range in a list of buffers.
71 template <typename Buffer, typename Buffers, typename Buffer_Iterator>
72 class consuming_buffers
73 {
74 public:
75 typedef prepared_buffers<Buffer, prepared_buffers_max<Buffers>::value>
76 prepared_buffers_type;
77
78 // Construct to represent the entire list of buffers.
79 explicit consuming_buffers(const Buffers& buffers)
80 : buffers_(buffers),
81 total_consumed_(0),
82 next_elem_(0),
83 next_elem_offset_(0)
84 {
85 using boost::asio::buffer_size;
86 total_size_ = buffer_size(buffers);
87 }
88
89 // Determine if we are at the end of the buffers.
90 bool empty() const
91 {
92 return total_consumed_ >= total_size_;
93 }
94
95 // Get the buffer for a single transfer, with a size.
96 prepared_buffers_type prepare(std::size_t max_size)
97 {
98 prepared_buffers_type result;
99
100 Buffer_Iterator next = boost::asio::buffer_sequence_begin(buffers_);
101 Buffer_Iterator end = boost::asio::buffer_sequence_end(buffers_);
102
103 std::advance(next, next_elem_);
104 std::size_t elem_offset = next_elem_offset_;
105 while (next != end && max_size > 0 && (result.count) < result.max_buffers)
106 {
107 Buffer next_buf = Buffer(*next) + elem_offset;
108 result.elems[result.count] = boost::asio::buffer(next_buf, max_size);
109 max_size -= result.elems[result.count].size();
110 elem_offset = 0;
111 if (result.elems[result.count].size() > 0)
112 ++result.count;
113 ++next;
114 }
115
116 return result;
117 }
118
119 // Consume the specified number of bytes from the buffers.
120 void consume(std::size_t size)
121 {
122 total_consumed_ += size;
123
124 Buffer_Iterator next = boost::asio::buffer_sequence_begin(buffers_);
125 Buffer_Iterator end = boost::asio::buffer_sequence_end(buffers_);
126
127 std::advance(next, next_elem_);
128 while (next != end && size > 0)
129 {
130 Buffer next_buf = Buffer(*next) + next_elem_offset_;
131 if (size < next_buf.size())
132 {
133 next_elem_offset_ += size;
134 size = 0;
135 }
136 else
137 {
138 size -= next_buf.size();
139 next_elem_offset_ = 0;
140 ++next_elem_;
141 ++next;
142 }
143 }
144 }
145
146 // Get the total number of bytes consumed from the buffers.
147 std::size_t total_consumed() const
148 {
149 return total_consumed_;
150 }
151
152 private:
153 Buffers buffers_;
154 std::size_t total_size_;
155 std::size_t total_consumed_;
156 std::size_t next_elem_;
157 std::size_t next_elem_offset_;
158 };
159
160 // Base class of all consuming_buffers specialisations for single buffers.
161 template <typename Buffer>
162 class consuming_single_buffer
163 {
164 public:
165 // Construct to represent the entire list of buffers.
166 template <typename Buffer1>
167 explicit consuming_single_buffer(const Buffer1& buffer)
168 : buffer_(buffer),
169 total_consumed_(0)
170 {
171 }
172
173 // Determine if we are at the end of the buffers.
174 bool empty() const
175 {
176 return total_consumed_ >= buffer_.size();
177 }
178
179 // Get the buffer for a single transfer, with a size.
180 Buffer prepare(std::size_t max_size)
181 {
182 return boost::asio::buffer(buffer_ + total_consumed_, max_size);
183 }
184
185 // Consume the specified number of bytes from the buffers.
186 void consume(std::size_t size)
187 {
188 total_consumed_ += size;
189 }
190
191 // Get the total number of bytes consumed from the buffers.
192 std::size_t total_consumed() const
193 {
194 return total_consumed_;
195 }
196
197 private:
198 Buffer buffer_;
199 std::size_t total_consumed_;
200 };
201
202 template <>
203 class consuming_buffers<mutable_buffer, mutable_buffer, const mutable_buffer*>
204 : public consuming_single_buffer<BOOST_ASIO_MUTABLE_BUFFER>
205 {
206 public:
207 explicit consuming_buffers(const mutable_buffer& buffer)
208 : consuming_single_buffer<BOOST_ASIO_MUTABLE_BUFFER>(buffer)
209 {
210 }
211 };
212
213 template <>
214 class consuming_buffers<const_buffer, mutable_buffer, const mutable_buffer*>
215 : public consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>
216 {
217 public:
218 explicit consuming_buffers(const mutable_buffer& buffer)
219 : consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>(buffer)
220 {
221 }
222 };
223
224 template <>
225 class consuming_buffers<const_buffer, const_buffer, const const_buffer*>
226 : public consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>
227 {
228 public:
229 explicit consuming_buffers(const const_buffer& buffer)
230 : consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>(buffer)
231 {
232 }
233 };
234
235 #if !defined(BOOST_ASIO_NO_DEPRECATED)
236
237 template <>
238 class consuming_buffers<mutable_buffer,
239 mutable_buffers_1, const mutable_buffer*>
240 : public consuming_single_buffer<BOOST_ASIO_MUTABLE_BUFFER>
241 {
242 public:
243 explicit consuming_buffers(const mutable_buffers_1& buffer)
244 : consuming_single_buffer<BOOST_ASIO_MUTABLE_BUFFER>(buffer)
245 {
246 }
247 };
248
249 template <>
250 class consuming_buffers<const_buffer, mutable_buffers_1, const mutable_buffer*>
251 : public consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>
252 {
253 public:
254 explicit consuming_buffers(const mutable_buffers_1& buffer)
255 : consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>(buffer)
256 {
257 }
258 };
259
260 template <>
261 class consuming_buffers<const_buffer, const_buffers_1, const const_buffer*>
262 : public consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>
263 {
264 public:
265 explicit consuming_buffers(const const_buffers_1& buffer)
266 : consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>(buffer)
267 {
268 }
269 };
270
271 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
272
273 template <typename Buffer, typename Elem>
274 class consuming_buffers<Buffer, boost::array<Elem, 2>,
275 typename boost::array<Elem, 2>::const_iterator>
276 {
277 public:
278 // Construct to represent the entire list of buffers.
279 explicit consuming_buffers(const boost::array<Elem, 2>& buffers)
280 : buffers_(buffers),
281 total_consumed_(0)
282 {
283 }
284
285 // Determine if we are at the end of the buffers.
286 bool empty() const
287 {
288 return total_consumed_ >=
289 Buffer(buffers_[0]).size() + Buffer(buffers_[1]).size();
290 }
291
292 // Get the buffer for a single transfer, with a size.
293 boost::array<Buffer, 2> prepare(std::size_t max_size)
294 {
295 boost::array<Buffer, 2> result = {{
296 Buffer(buffers_[0]), Buffer(buffers_[1]) }};
297 std::size_t buffer0_size = result[0].size();
298 result[0] = boost::asio::buffer(result[0] + total_consumed_, max_size);
299 result[1] = boost::asio::buffer(
300 result[1] + (total_consumed_ < buffer0_size
301 ? 0 : total_consumed_ - buffer0_size),
302 max_size - result[0].size());
303 return result;
304 }
305
306 // Consume the specified number of bytes from the buffers.
307 void consume(std::size_t size)
308 {
309 total_consumed_ += size;
310 }
311
312 // Get the total number of bytes consumed from the buffers.
313 std::size_t total_consumed() const
314 {
315 return total_consumed_;
316 }
317
318 private:
319 boost::array<Elem, 2> buffers_;
320 std::size_t total_consumed_;
321 };
322
323 #if defined(BOOST_ASIO_HAS_STD_ARRAY)
324
325 template <typename Buffer, typename Elem>
326 class consuming_buffers<Buffer, std::array<Elem, 2>,
327 typename std::array<Elem, 2>::const_iterator>
328 {
329 public:
330 // Construct to represent the entire list of buffers.
331 explicit consuming_buffers(const std::array<Elem, 2>& buffers)
332 : buffers_(buffers),
333 total_consumed_(0)
334 {
335 }
336
337 // Determine if we are at the end of the buffers.
338 bool empty() const
339 {
340 return total_consumed_ >=
341 Buffer(buffers_[0]).size() + Buffer(buffers_[1]).size();
342 }
343
344 // Get the buffer for a single transfer, with a size.
345 std::array<Buffer, 2> prepare(std::size_t max_size)
346 {
347 std::array<Buffer, 2> result = {{
348 Buffer(buffers_[0]), Buffer(buffers_[1]) }};
349 std::size_t buffer0_size = result[0].size();
350 result[0] = boost::asio::buffer(result[0] + total_consumed_, max_size);
351 result[1] = boost::asio::buffer(
352 result[1] + (total_consumed_ < buffer0_size
353 ? 0 : total_consumed_ - buffer0_size),
354 max_size - result[0].size());
355 return result;
356 }
357
358 // Consume the specified number of bytes from the buffers.
359 void consume(std::size_t size)
360 {
361 total_consumed_ += size;
362 }
363
364 // Get the total number of bytes consumed from the buffers.
365 std::size_t total_consumed() const
366 {
367 return total_consumed_;
368 }
369
370 private:
371 std::array<Elem, 2> buffers_;
372 std::size_t total_consumed_;
373 };
374
375 #endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
376
377 // Specialisation for null_buffers to ensure that the null_buffers type is
378 // always passed through to the underlying read or write operation.
379 template <typename Buffer>
380 class consuming_buffers<Buffer, null_buffers, const mutable_buffer*>
381 : public boost::asio::null_buffers
382 {
383 public:
384 consuming_buffers(const null_buffers&)
385 {
386 // No-op.
387 }
388
389 bool empty()
390 {
391 return false;
392 }
393
394 null_buffers prepare(std::size_t)
395 {
396 return null_buffers();
397 }
398
399 void consume(std::size_t)
400 {
401 // No-op.
402 }
403
404 std::size_t total_consumed() const
405 {
406 return 0;
407 }
408 };
409
410 } // namespace detail
411 } // namespace asio
412 } // namespace boost
413
414 #include <boost/asio/detail/pop_options.hpp>
415
416 #endif // BOOST_ASIO_DETAIL_CONSUMING_BUFFERS_HPP