1 //
2 // impl/read.hpp
3 // ~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2021 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_IMPL_READ_HPP
12 #define BOOST_ASIO_IMPL_READ_HPP
13
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18 #include <algorithm>
19 #include <boost/asio/associated_allocator.hpp>
20 #include <boost/asio/associated_executor.hpp>
21 #include <boost/asio/buffer.hpp>
22 #include <boost/asio/completion_condition.hpp>
23 #include <boost/asio/detail/array_fwd.hpp>
24 #include <boost/asio/detail/base_from_completion_cond.hpp>
25 #include <boost/asio/detail/bind_handler.hpp>
26 #include <boost/asio/detail/consuming_buffers.hpp>
27 #include <boost/asio/detail/dependent_type.hpp>
28 #include <boost/asio/detail/handler_alloc_helpers.hpp>
29 #include <boost/asio/detail/handler_cont_helpers.hpp>
30 #include <boost/asio/detail/handler_invoke_helpers.hpp>
31 #include <boost/asio/detail/handler_tracking.hpp>
32 #include <boost/asio/detail/handler_type_requirements.hpp>
33 #include <boost/asio/detail/non_const_lvalue.hpp>
34 #include <boost/asio/detail/throw_error.hpp>
35 #include <boost/asio/error.hpp>
36
37 #include <boost/asio/detail/push_options.hpp>
38
39 namespace boost {
40 namespace asio {
41
42 namespace detail
43 {
44 template <typename SyncReadStream, typename MutableBufferSequence,
45 typename MutableBufferIterator, typename CompletionCondition>
read_buffer_sequence(SyncReadStream & s,const MutableBufferSequence & buffers,const MutableBufferIterator &,CompletionCondition completion_condition,boost::system::error_code & ec)46 std::size_t read_buffer_sequence(SyncReadStream& s,
47 const MutableBufferSequence& buffers, const MutableBufferIterator&,
48 CompletionCondition completion_condition, boost::system::error_code& ec)
49 {
50 ec = boost::system::error_code();
51 boost::asio::detail::consuming_buffers<mutable_buffer,
52 MutableBufferSequence, MutableBufferIterator> tmp(buffers);
53 while (!tmp.empty())
54 {
55 if (std::size_t max_size = detail::adapt_completion_condition_result(
56 completion_condition(ec, tmp.total_consumed())))
57 tmp.consume(s.read_some(tmp.prepare(max_size), ec));
58 else
59 break;
60 }
61 return tmp.total_consumed();
62 }
63 } // namespace detail
64
65 template <typename SyncReadStream, typename MutableBufferSequence,
66 typename CompletionCondition>
read(SyncReadStream & s,const MutableBufferSequence & buffers,CompletionCondition completion_condition,boost::system::error_code & ec,typename constraint<is_mutable_buffer_sequence<MutableBufferSequence>::value>::type)67 std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
68 CompletionCondition completion_condition, boost::system::error_code& ec,
69 typename constraint<
70 is_mutable_buffer_sequence<MutableBufferSequence>::value
71 >::type)
72 {
73 return detail::read_buffer_sequence(s, buffers,
74 boost::asio::buffer_sequence_begin(buffers),
75 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
76 }
77
78 template <typename SyncReadStream, typename MutableBufferSequence>
read(SyncReadStream & s,const MutableBufferSequence & buffers,typename constraint<is_mutable_buffer_sequence<MutableBufferSequence>::value>::type)79 inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
80 typename constraint<
81 is_mutable_buffer_sequence<MutableBufferSequence>::value
82 >::type)
83 {
84 boost::system::error_code ec;
85 std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
86 boost::asio::detail::throw_error(ec, "read");
87 return bytes_transferred;
88 }
89
90 template <typename SyncReadStream, typename MutableBufferSequence>
read(SyncReadStream & s,const MutableBufferSequence & buffers,boost::system::error_code & ec,typename constraint<is_mutable_buffer_sequence<MutableBufferSequence>::value>::type)91 inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
92 boost::system::error_code& ec,
93 typename constraint<
94 is_mutable_buffer_sequence<MutableBufferSequence>::value
95 >::type)
96 {
97 return read(s, buffers, transfer_all(), ec);
98 }
99
100 template <typename SyncReadStream, typename MutableBufferSequence,
101 typename CompletionCondition>
read(SyncReadStream & s,const MutableBufferSequence & buffers,CompletionCondition completion_condition,typename constraint<is_mutable_buffer_sequence<MutableBufferSequence>::value>::type)102 inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
103 CompletionCondition completion_condition,
104 typename constraint<
105 is_mutable_buffer_sequence<MutableBufferSequence>::value
106 >::type)
107 {
108 boost::system::error_code ec;
109 std::size_t bytes_transferred = read(s, buffers,
110 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
111 boost::asio::detail::throw_error(ec, "read");
112 return bytes_transferred;
113 }
114
115 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
116
117 template <typename SyncReadStream, typename DynamicBuffer_v1,
118 typename CompletionCondition>
read(SyncReadStream & s,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,CompletionCondition completion_condition,boost::system::error_code & ec,typename constraint<is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value>::type,typename constraint<!is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value>::type)119 std::size_t read(SyncReadStream& s,
120 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
121 CompletionCondition completion_condition, boost::system::error_code& ec,
122 typename constraint<
123 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
124 >::type,
125 typename constraint<
126 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
127 >::type)
128 {
129 typename decay<DynamicBuffer_v1>::type b(
130 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
131
132 ec = boost::system::error_code();
133 std::size_t total_transferred = 0;
134 std::size_t max_size = detail::adapt_completion_condition_result(
135 completion_condition(ec, total_transferred));
136 std::size_t bytes_available = std::min<std::size_t>(
137 std::max<std::size_t>(512, b.capacity() - b.size()),
138 std::min<std::size_t>(max_size, b.max_size() - b.size()));
139 while (bytes_available > 0)
140 {
141 std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
142 b.commit(bytes_transferred);
143 total_transferred += bytes_transferred;
144 max_size = detail::adapt_completion_condition_result(
145 completion_condition(ec, total_transferred));
146 bytes_available = std::min<std::size_t>(
147 std::max<std::size_t>(512, b.capacity() - b.size()),
148 std::min<std::size_t>(max_size, b.max_size() - b.size()));
149 }
150 return total_transferred;
151 }
152
153 template <typename SyncReadStream, typename DynamicBuffer_v1>
read(SyncReadStream & s,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,typename constraint<is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value>::type,typename constraint<!is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value>::type)154 inline std::size_t read(SyncReadStream& s,
155 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
156 typename constraint<
157 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
158 >::type,
159 typename constraint<
160 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
161 >::type)
162 {
163 boost::system::error_code ec;
164 std::size_t bytes_transferred = read(s,
165 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), transfer_all(), ec);
166 boost::asio::detail::throw_error(ec, "read");
167 return bytes_transferred;
168 }
169
170 template <typename SyncReadStream, typename DynamicBuffer_v1>
read(SyncReadStream & s,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,boost::system::error_code & ec,typename constraint<is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value>::type,typename constraint<!is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value>::type)171 inline std::size_t read(SyncReadStream& s,
172 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
173 boost::system::error_code& ec,
174 typename constraint<
175 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
176 >::type,
177 typename constraint<
178 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
179 >::type)
180 {
181 return read(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
182 transfer_all(), ec);
183 }
184
185 template <typename SyncReadStream, typename DynamicBuffer_v1,
186 typename CompletionCondition>
read(SyncReadStream & s,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,CompletionCondition completion_condition,typename constraint<is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value>::type,typename constraint<!is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value>::type)187 inline std::size_t read(SyncReadStream& s,
188 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
189 CompletionCondition completion_condition,
190 typename constraint<
191 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
192 >::type,
193 typename constraint<
194 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
195 >::type)
196 {
197 boost::system::error_code ec;
198 std::size_t bytes_transferred = read(s,
199 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
200 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
201 boost::asio::detail::throw_error(ec, "read");
202 return bytes_transferred;
203 }
204
205 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
206 #if !defined(BOOST_ASIO_NO_IOSTREAM)
207
208 template <typename SyncReadStream, typename Allocator,
209 typename CompletionCondition>
read(SyncReadStream & s,boost::asio::basic_streambuf<Allocator> & b,CompletionCondition completion_condition,boost::system::error_code & ec)210 inline std::size_t read(SyncReadStream& s,
211 boost::asio::basic_streambuf<Allocator>& b,
212 CompletionCondition completion_condition, boost::system::error_code& ec)
213 {
214 return read(s, basic_streambuf_ref<Allocator>(b),
215 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
216 }
217
218 template <typename SyncReadStream, typename Allocator>
read(SyncReadStream & s,boost::asio::basic_streambuf<Allocator> & b)219 inline std::size_t read(SyncReadStream& s,
220 boost::asio::basic_streambuf<Allocator>& b)
221 {
222 return read(s, basic_streambuf_ref<Allocator>(b));
223 }
224
225 template <typename SyncReadStream, typename Allocator>
read(SyncReadStream & s,boost::asio::basic_streambuf<Allocator> & b,boost::system::error_code & ec)226 inline std::size_t read(SyncReadStream& s,
227 boost::asio::basic_streambuf<Allocator>& b,
228 boost::system::error_code& ec)
229 {
230 return read(s, basic_streambuf_ref<Allocator>(b), ec);
231 }
232
233 template <typename SyncReadStream, typename Allocator,
234 typename CompletionCondition>
read(SyncReadStream & s,boost::asio::basic_streambuf<Allocator> & b,CompletionCondition completion_condition)235 inline std::size_t read(SyncReadStream& s,
236 boost::asio::basic_streambuf<Allocator>& b,
237 CompletionCondition completion_condition)
238 {
239 return read(s, basic_streambuf_ref<Allocator>(b),
240 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
241 }
242
243 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
244 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
245 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
246
247 template <typename SyncReadStream, typename DynamicBuffer_v2,
248 typename CompletionCondition>
read(SyncReadStream & s,DynamicBuffer_v2 buffers,CompletionCondition completion_condition,boost::system::error_code & ec,typename constraint<is_dynamic_buffer_v2<DynamicBuffer_v2>::value>::type)249 std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
250 CompletionCondition completion_condition, boost::system::error_code& ec,
251 typename constraint<
252 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
253 >::type)
254 {
255 DynamicBuffer_v2& b = buffers;
256
257 ec = boost::system::error_code();
258 std::size_t total_transferred = 0;
259 std::size_t max_size = detail::adapt_completion_condition_result(
260 completion_condition(ec, total_transferred));
261 std::size_t bytes_available = std::min<std::size_t>(
262 std::max<std::size_t>(512, b.capacity() - b.size()),
263 std::min<std::size_t>(max_size, b.max_size() - b.size()));
264 while (bytes_available > 0)
265 {
266 std::size_t pos = b.size();
267 b.grow(bytes_available);
268 std::size_t bytes_transferred = s.read_some(
269 b.data(pos, bytes_available), ec);
270 b.shrink(bytes_available - bytes_transferred);
271 total_transferred += bytes_transferred;
272 max_size = detail::adapt_completion_condition_result(
273 completion_condition(ec, total_transferred));
274 bytes_available = std::min<std::size_t>(
275 std::max<std::size_t>(512, b.capacity() - b.size()),
276 std::min<std::size_t>(max_size, b.max_size() - b.size()));
277 }
278 return total_transferred;
279 }
280
281 template <typename SyncReadStream, typename DynamicBuffer_v2>
read(SyncReadStream & s,DynamicBuffer_v2 buffers,typename constraint<is_dynamic_buffer_v2<DynamicBuffer_v2>::value>::type)282 inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
283 typename constraint<
284 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
285 >::type)
286 {
287 boost::system::error_code ec;
288 std::size_t bytes_transferred = read(s,
289 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), transfer_all(), ec);
290 boost::asio::detail::throw_error(ec, "read");
291 return bytes_transferred;
292 }
293
294 template <typename SyncReadStream, typename DynamicBuffer_v2>
read(SyncReadStream & s,DynamicBuffer_v2 buffers,boost::system::error_code & ec,typename constraint<is_dynamic_buffer_v2<DynamicBuffer_v2>::value>::type)295 inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
296 boost::system::error_code& ec,
297 typename constraint<
298 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
299 >::type)
300 {
301 return read(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
302 transfer_all(), ec);
303 }
304
305 template <typename SyncReadStream, typename DynamicBuffer_v2,
306 typename CompletionCondition>
read(SyncReadStream & s,DynamicBuffer_v2 buffers,CompletionCondition completion_condition,typename constraint<is_dynamic_buffer_v2<DynamicBuffer_v2>::value>::type)307 inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
308 CompletionCondition completion_condition,
309 typename constraint<
310 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
311 >::type)
312 {
313 boost::system::error_code ec;
314 std::size_t bytes_transferred = read(s,
315 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
316 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
317 boost::asio::detail::throw_error(ec, "read");
318 return bytes_transferred;
319 }
320
321 namespace detail
322 {
323 template <typename AsyncReadStream, typename MutableBufferSequence,
324 typename MutableBufferIterator, typename CompletionCondition,
325 typename ReadHandler>
326 class read_op
327 : detail::base_from_completion_cond<CompletionCondition>
328 {
329 public:
read_op(AsyncReadStream & stream,const MutableBufferSequence & buffers,CompletionCondition & completion_condition,ReadHandler & handler)330 read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers,
331 CompletionCondition& completion_condition, ReadHandler& handler)
332 : detail::base_from_completion_cond<
333 CompletionCondition>(completion_condition),
334 stream_(stream),
335 buffers_(buffers),
336 start_(0),
337 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
338 {
339 }
340
341 #if defined(BOOST_ASIO_HAS_MOVE)
read_op(const read_op & other)342 read_op(const read_op& other)
343 : detail::base_from_completion_cond<CompletionCondition>(other),
344 stream_(other.stream_),
345 buffers_(other.buffers_),
346 start_(other.start_),
347 handler_(other.handler_)
348 {
349 }
350
read_op(read_op && other)351 read_op(read_op&& other)
352 : detail::base_from_completion_cond<CompletionCondition>(
353 BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
354 CompletionCondition>)(other)),
355 stream_(other.stream_),
356 buffers_(BOOST_ASIO_MOVE_CAST(buffers_type)(other.buffers_)),
357 start_(other.start_),
358 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
359 {
360 }
361 #endif // defined(BOOST_ASIO_HAS_MOVE)
362
operator ()(const boost::system::error_code & ec,std::size_t bytes_transferred,int start=0)363 void operator()(const boost::system::error_code& ec,
364 std::size_t bytes_transferred, int start = 0)
365 {
366 std::size_t max_size;
367 switch (start_ = start)
368 {
369 case 1:
370 max_size = this->check_for_completion(ec, buffers_.total_consumed());
371 do
372 {
373 {
374 BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));
375 stream_.async_read_some(buffers_.prepare(max_size),
376 BOOST_ASIO_MOVE_CAST(read_op)(*this));
377 }
378 return; default:
379 buffers_.consume(bytes_transferred);
380 if ((!ec && bytes_transferred == 0) || buffers_.empty())
381 break;
382 max_size = this->check_for_completion(ec, buffers_.total_consumed());
383 } while (max_size > 0);
384
385 handler_(ec, buffers_.total_consumed());
386 }
387 }
388
389 //private:
390 typedef boost::asio::detail::consuming_buffers<mutable_buffer,
391 MutableBufferSequence, MutableBufferIterator> buffers_type;
392
393 AsyncReadStream& stream_;
394 buffers_type buffers_;
395 int start_;
396 ReadHandler handler_;
397 };
398
399 template <typename AsyncReadStream, typename MutableBufferSequence,
400 typename MutableBufferIterator, typename CompletionCondition,
401 typename ReadHandler>
402 inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,read_op<AsyncReadStream,MutableBufferSequence,MutableBufferIterator,CompletionCondition,ReadHandler> * this_handler)403 asio_handler_allocate(std::size_t size,
404 read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
405 CompletionCondition, ReadHandler>* this_handler)
406 {
407 #if defined(BOOST_ASIO_NO_DEPRECATED)
408 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
409 return asio_handler_allocate_is_no_longer_used();
410 #else // defined(BOOST_ASIO_NO_DEPRECATED)
411 return boost_asio_handler_alloc_helpers::allocate(
412 size, this_handler->handler_);
413 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
414 }
415
416 template <typename AsyncReadStream, typename MutableBufferSequence,
417 typename MutableBufferIterator, typename CompletionCondition,
418 typename ReadHandler>
419 inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void * pointer,std::size_t size,read_op<AsyncReadStream,MutableBufferSequence,MutableBufferIterator,CompletionCondition,ReadHandler> * this_handler)420 asio_handler_deallocate(void* pointer, std::size_t size,
421 read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
422 CompletionCondition, ReadHandler>* this_handler)
423 {
424 boost_asio_handler_alloc_helpers::deallocate(
425 pointer, size, this_handler->handler_);
426 #if defined(BOOST_ASIO_NO_DEPRECATED)
427 return asio_handler_deallocate_is_no_longer_used();
428 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
429 }
430
431 template <typename AsyncReadStream, typename MutableBufferSequence,
432 typename MutableBufferIterator, typename CompletionCondition,
433 typename ReadHandler>
asio_handler_is_continuation(read_op<AsyncReadStream,MutableBufferSequence,MutableBufferIterator,CompletionCondition,ReadHandler> * this_handler)434 inline bool asio_handler_is_continuation(
435 read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
436 CompletionCondition, ReadHandler>* this_handler)
437 {
438 return this_handler->start_ == 0 ? true
439 : boost_asio_handler_cont_helpers::is_continuation(
440 this_handler->handler_);
441 }
442
443 template <typename Function, typename AsyncReadStream,
444 typename MutableBufferSequence, typename MutableBufferIterator,
445 typename CompletionCondition, typename ReadHandler>
446 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function & function,read_op<AsyncReadStream,MutableBufferSequence,MutableBufferIterator,CompletionCondition,ReadHandler> * this_handler)447 asio_handler_invoke(Function& function,
448 read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
449 CompletionCondition, ReadHandler>* this_handler)
450 {
451 boost_asio_handler_invoke_helpers::invoke(
452 function, this_handler->handler_);
453 #if defined(BOOST_ASIO_NO_DEPRECATED)
454 return asio_handler_invoke_is_no_longer_used();
455 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
456 }
457
458 template <typename Function, typename AsyncReadStream,
459 typename MutableBufferSequence, typename MutableBufferIterator,
460 typename CompletionCondition, typename ReadHandler>
461 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function & function,read_op<AsyncReadStream,MutableBufferSequence,MutableBufferIterator,CompletionCondition,ReadHandler> * this_handler)462 asio_handler_invoke(const Function& function,
463 read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
464 CompletionCondition, ReadHandler>* this_handler)
465 {
466 boost_asio_handler_invoke_helpers::invoke(
467 function, this_handler->handler_);
468 #if defined(BOOST_ASIO_NO_DEPRECATED)
469 return asio_handler_invoke_is_no_longer_used();
470 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
471 }
472
473 template <typename AsyncReadStream, typename MutableBufferSequence,
474 typename MutableBufferIterator, typename CompletionCondition,
475 typename ReadHandler>
start_read_buffer_sequence_op(AsyncReadStream & stream,const MutableBufferSequence & buffers,const MutableBufferIterator &,CompletionCondition & completion_condition,ReadHandler & handler)476 inline void start_read_buffer_sequence_op(AsyncReadStream& stream,
477 const MutableBufferSequence& buffers, const MutableBufferIterator&,
478 CompletionCondition& completion_condition, ReadHandler& handler)
479 {
480 detail::read_op<AsyncReadStream, MutableBufferSequence,
481 MutableBufferIterator, CompletionCondition, ReadHandler>(
482 stream, buffers, completion_condition, handler)(
483 boost::system::error_code(), 0, 1);
484 }
485
486 template <typename AsyncReadStream>
487 class initiate_async_read_buffer_sequence
488 {
489 public:
490 typedef typename AsyncReadStream::executor_type executor_type;
491
initiate_async_read_buffer_sequence(AsyncReadStream & stream)492 explicit initiate_async_read_buffer_sequence(AsyncReadStream& stream)
493 : stream_(stream)
494 {
495 }
496
get_executor() const497 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
498 {
499 return stream_.get_executor();
500 }
501
502 template <typename ReadHandler, typename MutableBufferSequence,
503 typename CompletionCondition>
operator ()(BOOST_ASIO_MOVE_ARG (ReadHandler)handler,const MutableBufferSequence & buffers,BOOST_ASIO_MOVE_ARG (CompletionCondition)completion_cond) const504 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
505 const MutableBufferSequence& buffers,
506 BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
507 {
508 // If you get an error on the following line it means that your handler
509 // does not meet the documented type requirements for a ReadHandler.
510 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
511
512 non_const_lvalue<ReadHandler> handler2(handler);
513 non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
514 start_read_buffer_sequence_op(stream_, buffers,
515 boost::asio::buffer_sequence_begin(buffers),
516 completion_cond2.value, handler2.value);
517 }
518
519 private:
520 AsyncReadStream& stream_;
521 };
522 } // namespace detail
523
524 #if !defined(GENERATING_DOCUMENTATION)
525
526 template <typename AsyncReadStream, typename MutableBufferSequence,
527 typename MutableBufferIterator, typename CompletionCondition,
528 typename ReadHandler, typename Allocator>
529 struct associated_allocator<
530 detail::read_op<AsyncReadStream, MutableBufferSequence,
531 MutableBufferIterator, CompletionCondition, ReadHandler>,
532 Allocator>
533 {
534 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
535
getboost::asio::associated_allocator536 static type get(
537 const detail::read_op<AsyncReadStream, MutableBufferSequence,
538 MutableBufferIterator, CompletionCondition, ReadHandler>& h,
539 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
540 {
541 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
542 }
543 };
544
545 template <typename AsyncReadStream, typename MutableBufferSequence,
546 typename MutableBufferIterator, typename CompletionCondition,
547 typename ReadHandler, typename Executor>
548 struct associated_executor<
549 detail::read_op<AsyncReadStream, MutableBufferSequence,
550 MutableBufferIterator, CompletionCondition, ReadHandler>,
551 Executor>
552 : detail::associated_executor_forwarding_base<ReadHandler, Executor>
553 {
554 typedef typename associated_executor<ReadHandler, Executor>::type type;
555
getboost::asio::associated_executor556 static type get(
557 const detail::read_op<AsyncReadStream, MutableBufferSequence,
558 MutableBufferIterator, CompletionCondition, ReadHandler>& h,
559 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
560 {
561 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
562 }
563 };
564
565 #endif // !defined(GENERATING_DOCUMENTATION)
566
567 template <typename AsyncReadStream,
568 typename MutableBufferSequence, typename CompletionCondition,
569 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
570 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))571 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
572 void (boost::system::error_code, std::size_t))
573 async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
574 CompletionCondition completion_condition,
575 BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
576 typename constraint<
577 is_mutable_buffer_sequence<MutableBufferSequence>::value
578 >::type)
579 {
580 return async_initiate<ReadHandler,
581 void (boost::system::error_code, std::size_t)>(
582 detail::initiate_async_read_buffer_sequence<AsyncReadStream>(s), handler,
583 buffers, BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
584 }
585
586 template <typename AsyncReadStream, typename MutableBufferSequence,
587 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
588 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))589 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
590 void (boost::system::error_code, std::size_t))
591 async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
592 BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
593 typename constraint<
594 is_mutable_buffer_sequence<MutableBufferSequence>::value
595 >::type)
596 {
597 return async_initiate<ReadHandler,
598 void (boost::system::error_code, std::size_t)>(
599 detail::initiate_async_read_buffer_sequence<AsyncReadStream>(s),
600 handler, buffers, transfer_all());
601 }
602
603 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
604
605 namespace detail
606 {
607 template <typename AsyncReadStream, typename DynamicBuffer_v1,
608 typename CompletionCondition, typename ReadHandler>
609 class read_dynbuf_v1_op
610 : detail::base_from_completion_cond<CompletionCondition>
611 {
612 public:
613 template <typename BufferSequence>
read_dynbuf_v1_op(AsyncReadStream & stream,BOOST_ASIO_MOVE_ARG (BufferSequence)buffers,CompletionCondition & completion_condition,ReadHandler & handler)614 read_dynbuf_v1_op(AsyncReadStream& stream,
615 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
616 CompletionCondition& completion_condition, ReadHandler& handler)
617 : detail::base_from_completion_cond<
618 CompletionCondition>(completion_condition),
619 stream_(stream),
620 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
621 start_(0),
622 total_transferred_(0),
623 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
624 {
625 }
626
627 #if defined(BOOST_ASIO_HAS_MOVE)
read_dynbuf_v1_op(const read_dynbuf_v1_op & other)628 read_dynbuf_v1_op(const read_dynbuf_v1_op& other)
629 : detail::base_from_completion_cond<CompletionCondition>(other),
630 stream_(other.stream_),
631 buffers_(other.buffers_),
632 start_(other.start_),
633 total_transferred_(other.total_transferred_),
634 handler_(other.handler_)
635 {
636 }
637
read_dynbuf_v1_op(read_dynbuf_v1_op && other)638 read_dynbuf_v1_op(read_dynbuf_v1_op&& other)
639 : detail::base_from_completion_cond<CompletionCondition>(
640 BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
641 CompletionCondition>)(other)),
642 stream_(other.stream_),
643 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
644 start_(other.start_),
645 total_transferred_(other.total_transferred_),
646 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
647 {
648 }
649 #endif // defined(BOOST_ASIO_HAS_MOVE)
650
operator ()(const boost::system::error_code & ec,std::size_t bytes_transferred,int start=0)651 void operator()(const boost::system::error_code& ec,
652 std::size_t bytes_transferred, int start = 0)
653 {
654 std::size_t max_size, bytes_available;
655 switch (start_ = start)
656 {
657 case 1:
658 max_size = this->check_for_completion(ec, total_transferred_);
659 bytes_available = std::min<std::size_t>(
660 std::max<std::size_t>(512,
661 buffers_.capacity() - buffers_.size()),
662 std::min<std::size_t>(max_size,
663 buffers_.max_size() - buffers_.size()));
664 for (;;)
665 {
666 {
667 BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));
668 stream_.async_read_some(buffers_.prepare(bytes_available),
669 BOOST_ASIO_MOVE_CAST(read_dynbuf_v1_op)(*this));
670 }
671 return; default:
672 total_transferred_ += bytes_transferred;
673 buffers_.commit(bytes_transferred);
674 max_size = this->check_for_completion(ec, total_transferred_);
675 bytes_available = std::min<std::size_t>(
676 std::max<std::size_t>(512,
677 buffers_.capacity() - buffers_.size()),
678 std::min<std::size_t>(max_size,
679 buffers_.max_size() - buffers_.size()));
680 if ((!ec && bytes_transferred == 0) || bytes_available == 0)
681 break;
682 }
683
684 handler_(ec, static_cast<const std::size_t&>(total_transferred_));
685 }
686 }
687
688 //private:
689 AsyncReadStream& stream_;
690 DynamicBuffer_v1 buffers_;
691 int start_;
692 std::size_t total_transferred_;
693 ReadHandler handler_;
694 };
695
696 template <typename AsyncReadStream, typename DynamicBuffer_v1,
697 typename CompletionCondition, typename ReadHandler>
698 inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,read_dynbuf_v1_op<AsyncReadStream,DynamicBuffer_v1,CompletionCondition,ReadHandler> * this_handler)699 asio_handler_allocate(std::size_t size,
700 read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
701 CompletionCondition, ReadHandler>* this_handler)
702 {
703 #if defined(BOOST_ASIO_NO_DEPRECATED)
704 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
705 return asio_handler_allocate_is_no_longer_used();
706 #else // defined(BOOST_ASIO_NO_DEPRECATED)
707 return boost_asio_handler_alloc_helpers::allocate(
708 size, this_handler->handler_);
709 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
710 }
711
712 template <typename AsyncReadStream, typename DynamicBuffer_v1,
713 typename CompletionCondition, typename ReadHandler>
714 inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void * pointer,std::size_t size,read_dynbuf_v1_op<AsyncReadStream,DynamicBuffer_v1,CompletionCondition,ReadHandler> * this_handler)715 asio_handler_deallocate(void* pointer, std::size_t size,
716 read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
717 CompletionCondition, ReadHandler>* this_handler)
718 {
719 boost_asio_handler_alloc_helpers::deallocate(
720 pointer, size, this_handler->handler_);
721 #if defined(BOOST_ASIO_NO_DEPRECATED)
722 return asio_handler_deallocate_is_no_longer_used();
723 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
724 }
725
726 template <typename AsyncReadStream, typename DynamicBuffer_v1,
727 typename CompletionCondition, typename ReadHandler>
asio_handler_is_continuation(read_dynbuf_v1_op<AsyncReadStream,DynamicBuffer_v1,CompletionCondition,ReadHandler> * this_handler)728 inline bool asio_handler_is_continuation(
729 read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
730 CompletionCondition, ReadHandler>* this_handler)
731 {
732 return this_handler->start_ == 0 ? true
733 : boost_asio_handler_cont_helpers::is_continuation(
734 this_handler->handler_);
735 }
736
737 template <typename Function, typename AsyncReadStream,
738 typename DynamicBuffer_v1, typename CompletionCondition,
739 typename ReadHandler>
740 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function & function,read_dynbuf_v1_op<AsyncReadStream,DynamicBuffer_v1,CompletionCondition,ReadHandler> * this_handler)741 asio_handler_invoke(Function& function,
742 read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
743 CompletionCondition, ReadHandler>* this_handler)
744 {
745 boost_asio_handler_invoke_helpers::invoke(
746 function, this_handler->handler_);
747 #if defined(BOOST_ASIO_NO_DEPRECATED)
748 return asio_handler_invoke_is_no_longer_used();
749 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
750 }
751
752 template <typename Function, typename AsyncReadStream,
753 typename DynamicBuffer_v1, typename CompletionCondition,
754 typename ReadHandler>
755 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function & function,read_dynbuf_v1_op<AsyncReadStream,DynamicBuffer_v1,CompletionCondition,ReadHandler> * this_handler)756 asio_handler_invoke(const Function& function,
757 read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
758 CompletionCondition, ReadHandler>* this_handler)
759 {
760 boost_asio_handler_invoke_helpers::invoke(
761 function, this_handler->handler_);
762 #if defined(BOOST_ASIO_NO_DEPRECATED)
763 return asio_handler_invoke_is_no_longer_used();
764 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
765 }
766
767 template <typename AsyncReadStream>
768 class initiate_async_read_dynbuf_v1
769 {
770 public:
771 typedef typename AsyncReadStream::executor_type executor_type;
772
initiate_async_read_dynbuf_v1(AsyncReadStream & stream)773 explicit initiate_async_read_dynbuf_v1(AsyncReadStream& stream)
774 : stream_(stream)
775 {
776 }
777
get_executor() const778 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
779 {
780 return stream_.get_executor();
781 }
782
783 template <typename ReadHandler, typename DynamicBuffer_v1,
784 typename CompletionCondition>
operator ()(BOOST_ASIO_MOVE_ARG (ReadHandler)handler,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,BOOST_ASIO_MOVE_ARG (CompletionCondition)completion_cond) const785 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
786 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
787 BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
788 {
789 // If you get an error on the following line it means that your handler
790 // does not meet the documented type requirements for a ReadHandler.
791 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
792
793 non_const_lvalue<ReadHandler> handler2(handler);
794 non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
795 read_dynbuf_v1_op<AsyncReadStream, typename decay<DynamicBuffer_v1>::type,
796 CompletionCondition, typename decay<ReadHandler>::type>(
797 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
798 completion_cond2.value, handler2.value)(
799 boost::system::error_code(), 0, 1);
800 }
801
802 private:
803 AsyncReadStream& stream_;
804 };
805 } // namespace detail
806
807 #if !defined(GENERATING_DOCUMENTATION)
808
809 template <typename AsyncReadStream, typename DynamicBuffer_v1,
810 typename CompletionCondition, typename ReadHandler, typename Allocator>
811 struct associated_allocator<
812 detail::read_dynbuf_v1_op<AsyncReadStream,
813 DynamicBuffer_v1, CompletionCondition, ReadHandler>,
814 Allocator>
815 {
816 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
817
getboost::asio::associated_allocator818 static type get(
819 const detail::read_dynbuf_v1_op<AsyncReadStream,
820 DynamicBuffer_v1, CompletionCondition, ReadHandler>& h,
821 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
822 {
823 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
824 }
825 };
826
827 template <typename AsyncReadStream, typename DynamicBuffer_v1,
828 typename CompletionCondition, typename ReadHandler, typename Executor>
829 struct associated_executor<
830 detail::read_dynbuf_v1_op<AsyncReadStream,
831 DynamicBuffer_v1, CompletionCondition, ReadHandler>,
832 Executor>
833 : detail::associated_executor_forwarding_base<ReadHandler, Executor>
834 {
835 typedef typename associated_executor<ReadHandler, Executor>::type type;
836
getboost::asio::associated_executor837 static type get(
838 const detail::read_dynbuf_v1_op<AsyncReadStream,
839 DynamicBuffer_v1, CompletionCondition, ReadHandler>& h,
840 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
841 {
842 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
843 }
844 };
845
846 #endif // !defined(GENERATING_DOCUMENTATION)
847
848 template <typename AsyncReadStream, typename DynamicBuffer_v1,
849 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
850 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))851 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
852 void (boost::system::error_code, std::size_t))
853 async_read(AsyncReadStream& s,
854 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
855 BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
856 typename constraint<
857 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
858 >::type,
859 typename constraint<
860 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
861 >::type)
862 {
863 return async_read(s,
864 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
865 transfer_all(), BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
866 }
867
868 template <typename AsyncReadStream,
869 typename DynamicBuffer_v1, typename CompletionCondition,
870 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
871 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))872 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
873 void (boost::system::error_code, std::size_t))
874 async_read(AsyncReadStream& s,
875 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
876 CompletionCondition completion_condition,
877 BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
878 typename constraint<
879 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
880 >::type,
881 typename constraint<
882 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
883 >::type)
884 {
885 return async_initiate<ReadHandler,
886 void (boost::system::error_code, std::size_t)>(
887 detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s),
888 handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
889 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
890 }
891
892 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
893 #if !defined(BOOST_ASIO_NO_IOSTREAM)
894
895 template <typename AsyncReadStream, typename Allocator,
896 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
897 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))898 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
899 void (boost::system::error_code, std::size_t))
900 async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
901 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
902 {
903 return async_read(s, basic_streambuf_ref<Allocator>(b),
904 BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
905 }
906
907 template <typename AsyncReadStream,
908 typename Allocator, typename CompletionCondition,
909 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
910 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))911 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
912 void (boost::system::error_code, std::size_t))
913 async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
914 CompletionCondition completion_condition,
915 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
916 {
917 return async_read(s, basic_streambuf_ref<Allocator>(b),
918 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition),
919 BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
920 }
921
922 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
923 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
924 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
925
926 namespace detail
927 {
928 template <typename AsyncReadStream, typename DynamicBuffer_v2,
929 typename CompletionCondition, typename ReadHandler>
930 class read_dynbuf_v2_op
931 : detail::base_from_completion_cond<CompletionCondition>
932 {
933 public:
934 template <typename BufferSequence>
read_dynbuf_v2_op(AsyncReadStream & stream,BOOST_ASIO_MOVE_ARG (BufferSequence)buffers,CompletionCondition & completion_condition,ReadHandler & handler)935 read_dynbuf_v2_op(AsyncReadStream& stream,
936 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
937 CompletionCondition& completion_condition, ReadHandler& handler)
938 : detail::base_from_completion_cond<
939 CompletionCondition>(completion_condition),
940 stream_(stream),
941 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
942 start_(0),
943 total_transferred_(0),
944 bytes_available_(0),
945 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
946 {
947 }
948
949 #if defined(BOOST_ASIO_HAS_MOVE)
read_dynbuf_v2_op(const read_dynbuf_v2_op & other)950 read_dynbuf_v2_op(const read_dynbuf_v2_op& other)
951 : detail::base_from_completion_cond<CompletionCondition>(other),
952 stream_(other.stream_),
953 buffers_(other.buffers_),
954 start_(other.start_),
955 total_transferred_(other.total_transferred_),
956 bytes_available_(other.bytes_available_),
957 handler_(other.handler_)
958 {
959 }
960
read_dynbuf_v2_op(read_dynbuf_v2_op && other)961 read_dynbuf_v2_op(read_dynbuf_v2_op&& other)
962 : detail::base_from_completion_cond<CompletionCondition>(
963 BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
964 CompletionCondition>)(other)),
965 stream_(other.stream_),
966 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
967 start_(other.start_),
968 total_transferred_(other.total_transferred_),
969 bytes_available_(other.bytes_available_),
970 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
971 {
972 }
973 #endif // defined(BOOST_ASIO_HAS_MOVE)
974
operator ()(const boost::system::error_code & ec,std::size_t bytes_transferred,int start=0)975 void operator()(const boost::system::error_code& ec,
976 std::size_t bytes_transferred, int start = 0)
977 {
978 std::size_t max_size, pos;
979 switch (start_ = start)
980 {
981 case 1:
982 max_size = this->check_for_completion(ec, total_transferred_);
983 bytes_available_ = std::min<std::size_t>(
984 std::max<std::size_t>(512,
985 buffers_.capacity() - buffers_.size()),
986 std::min<std::size_t>(max_size,
987 buffers_.max_size() - buffers_.size()));
988 for (;;)
989 {
990 pos = buffers_.size();
991 buffers_.grow(bytes_available_);
992 {
993 BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));
994 stream_.async_read_some(buffers_.data(pos, bytes_available_),
995 BOOST_ASIO_MOVE_CAST(read_dynbuf_v2_op)(*this));
996 }
997 return; default:
998 total_transferred_ += bytes_transferred;
999 buffers_.shrink(bytes_available_ - bytes_transferred);
1000 max_size = this->check_for_completion(ec, total_transferred_);
1001 bytes_available_ = std::min<std::size_t>(
1002 std::max<std::size_t>(512,
1003 buffers_.capacity() - buffers_.size()),
1004 std::min<std::size_t>(max_size,
1005 buffers_.max_size() - buffers_.size()));
1006 if ((!ec && bytes_transferred == 0) || bytes_available_ == 0)
1007 break;
1008 }
1009
1010 handler_(ec, static_cast<const std::size_t&>(total_transferred_));
1011 }
1012 }
1013
1014 //private:
1015 AsyncReadStream& stream_;
1016 DynamicBuffer_v2 buffers_;
1017 int start_;
1018 std::size_t total_transferred_;
1019 std::size_t bytes_available_;
1020 ReadHandler handler_;
1021 };
1022
1023 template <typename AsyncReadStream, typename DynamicBuffer_v2,
1024 typename CompletionCondition, typename ReadHandler>
1025 inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,read_dynbuf_v2_op<AsyncReadStream,DynamicBuffer_v2,CompletionCondition,ReadHandler> * this_handler)1026 asio_handler_allocate(std::size_t size,
1027 read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
1028 CompletionCondition, ReadHandler>* this_handler)
1029 {
1030 #if defined(BOOST_ASIO_NO_DEPRECATED)
1031 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
1032 return asio_handler_allocate_is_no_longer_used();
1033 #else // defined(BOOST_ASIO_NO_DEPRECATED)
1034 return boost_asio_handler_alloc_helpers::allocate(
1035 size, this_handler->handler_);
1036 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1037 }
1038
1039 template <typename AsyncReadStream, typename DynamicBuffer_v2,
1040 typename CompletionCondition, typename ReadHandler>
1041 inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void * pointer,std::size_t size,read_dynbuf_v2_op<AsyncReadStream,DynamicBuffer_v2,CompletionCondition,ReadHandler> * this_handler)1042 asio_handler_deallocate(void* pointer, std::size_t size,
1043 read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
1044 CompletionCondition, ReadHandler>* this_handler)
1045 {
1046 boost_asio_handler_alloc_helpers::deallocate(
1047 pointer, size, this_handler->handler_);
1048 #if defined(BOOST_ASIO_NO_DEPRECATED)
1049 return asio_handler_deallocate_is_no_longer_used();
1050 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1051 }
1052
1053 template <typename AsyncReadStream, typename DynamicBuffer_v2,
1054 typename CompletionCondition, typename ReadHandler>
asio_handler_is_continuation(read_dynbuf_v2_op<AsyncReadStream,DynamicBuffer_v2,CompletionCondition,ReadHandler> * this_handler)1055 inline bool asio_handler_is_continuation(
1056 read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
1057 CompletionCondition, ReadHandler>* this_handler)
1058 {
1059 return this_handler->start_ == 0 ? true
1060 : boost_asio_handler_cont_helpers::is_continuation(
1061 this_handler->handler_);
1062 }
1063
1064 template <typename Function, typename AsyncReadStream,
1065 typename DynamicBuffer_v2, typename CompletionCondition,
1066 typename ReadHandler>
1067 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function & function,read_dynbuf_v2_op<AsyncReadStream,DynamicBuffer_v2,CompletionCondition,ReadHandler> * this_handler)1068 asio_handler_invoke(Function& function,
1069 read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
1070 CompletionCondition, ReadHandler>* this_handler)
1071 {
1072 boost_asio_handler_invoke_helpers::invoke(
1073 function, this_handler->handler_);
1074 #if defined(BOOST_ASIO_NO_DEPRECATED)
1075 return asio_handler_invoke_is_no_longer_used();
1076 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1077 }
1078
1079 template <typename Function, typename AsyncReadStream,
1080 typename DynamicBuffer_v2, typename CompletionCondition,
1081 typename ReadHandler>
1082 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function & function,read_dynbuf_v2_op<AsyncReadStream,DynamicBuffer_v2,CompletionCondition,ReadHandler> * this_handler)1083 asio_handler_invoke(const Function& function,
1084 read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
1085 CompletionCondition, ReadHandler>* this_handler)
1086 {
1087 boost_asio_handler_invoke_helpers::invoke(
1088 function, this_handler->handler_);
1089 #if defined(BOOST_ASIO_NO_DEPRECATED)
1090 return asio_handler_invoke_is_no_longer_used();
1091 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1092 }
1093
1094 template <typename AsyncReadStream>
1095 class initiate_async_read_dynbuf_v2
1096 {
1097 public:
1098 typedef typename AsyncReadStream::executor_type executor_type;
1099
initiate_async_read_dynbuf_v2(AsyncReadStream & stream)1100 explicit initiate_async_read_dynbuf_v2(AsyncReadStream& stream)
1101 : stream_(stream)
1102 {
1103 }
1104
get_executor() const1105 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
1106 {
1107 return stream_.get_executor();
1108 }
1109
1110 template <typename ReadHandler, typename DynamicBuffer_v2,
1111 typename CompletionCondition>
operator ()(BOOST_ASIO_MOVE_ARG (ReadHandler)handler,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v2)buffers,BOOST_ASIO_MOVE_ARG (CompletionCondition)completion_cond) const1112 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1113 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
1114 BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
1115 {
1116 // If you get an error on the following line it means that your handler
1117 // does not meet the documented type requirements for a ReadHandler.
1118 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1119
1120 non_const_lvalue<ReadHandler> handler2(handler);
1121 non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
1122 read_dynbuf_v2_op<AsyncReadStream, typename decay<DynamicBuffer_v2>::type,
1123 CompletionCondition, typename decay<ReadHandler>::type>(
1124 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
1125 completion_cond2.value, handler2.value)(
1126 boost::system::error_code(), 0, 1);
1127 }
1128
1129 private:
1130 AsyncReadStream& stream_;
1131 };
1132 } // namespace detail
1133
1134 #if !defined(GENERATING_DOCUMENTATION)
1135
1136 template <typename AsyncReadStream, typename DynamicBuffer_v2,
1137 typename CompletionCondition, typename ReadHandler, typename Allocator>
1138 struct associated_allocator<
1139 detail::read_dynbuf_v2_op<AsyncReadStream,
1140 DynamicBuffer_v2, CompletionCondition, ReadHandler>,
1141 Allocator>
1142 {
1143 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
1144
getboost::asio::associated_allocator1145 static type get(
1146 const detail::read_dynbuf_v2_op<AsyncReadStream,
1147 DynamicBuffer_v2, CompletionCondition, ReadHandler>& h,
1148 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
1149 {
1150 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
1151 }
1152 };
1153
1154 template <typename AsyncReadStream, typename DynamicBuffer_v2,
1155 typename CompletionCondition, typename ReadHandler, typename Executor>
1156 struct associated_executor<
1157 detail::read_dynbuf_v2_op<AsyncReadStream,
1158 DynamicBuffer_v2, CompletionCondition, ReadHandler>,
1159 Executor>
1160 : detail::associated_executor_forwarding_base<ReadHandler, Executor>
1161 {
1162 typedef typename associated_executor<ReadHandler, Executor>::type type;
1163
getboost::asio::associated_executor1164 static type get(
1165 const detail::read_dynbuf_v2_op<AsyncReadStream,
1166 DynamicBuffer_v2, CompletionCondition, ReadHandler>& h,
1167 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
1168 {
1169 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
1170 }
1171 };
1172
1173 #endif // !defined(GENERATING_DOCUMENTATION)
1174
1175 template <typename AsyncReadStream, typename DynamicBuffer_v2,
1176 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1177 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))1178 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
1179 void (boost::system::error_code, std::size_t))
1180 async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,
1181 BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1182 typename constraint<
1183 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
1184 >::type)
1185 {
1186 return async_read(s,
1187 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
1188 transfer_all(), BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
1189 }
1190
1191 template <typename AsyncReadStream,
1192 typename DynamicBuffer_v2, typename CompletionCondition,
1193 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1194 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))1195 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
1196 void (boost::system::error_code, std::size_t))
1197 async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,
1198 CompletionCondition completion_condition,
1199 BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1200 typename constraint<
1201 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
1202 >::type)
1203 {
1204 return async_initiate<ReadHandler,
1205 void (boost::system::error_code, std::size_t)>(
1206 detail::initiate_async_read_dynbuf_v2<AsyncReadStream>(s),
1207 handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
1208 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
1209 }
1210
1211 } // namespace asio
1212 } // namespace boost
1213
1214 #include <boost/asio/detail/pop_options.hpp>
1215
1216 #endif // BOOST_ASIO_IMPL_READ_HPP
1217