5 // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_IMPL_READ_HPP
12 #define BOOST_ASIO_IMPL_READ_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
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_type_requirements.hpp>
32 #include <boost/asio/detail/non_const_lvalue.hpp>
33 #include <boost/asio/detail/throw_error.hpp>
34 #include <boost/asio/error.hpp>
36 #include <boost/asio/detail/push_options.hpp>
43 template <typename SyncReadStream, typename MutableBufferSequence,
44 typename MutableBufferIterator, typename CompletionCondition>
45 std::size_t read_buffer_sequence(SyncReadStream& s,
46 const MutableBufferSequence& buffers, const MutableBufferIterator&,
47 CompletionCondition completion_condition, boost::system::error_code& ec)
49 ec = boost::system::error_code();
50 boost::asio::detail::consuming_buffers<mutable_buffer,
51 MutableBufferSequence, MutableBufferIterator> tmp(buffers);
54 if (std::size_t max_size = detail::adapt_completion_condition_result(
55 completion_condition(ec, tmp.total_consumed())))
56 tmp.consume(s.read_some(tmp.prepare(max_size), ec));
60 return tmp.total_consumed();;
64 template <typename SyncReadStream, typename MutableBufferSequence,
65 typename CompletionCondition>
66 std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
67 CompletionCondition completion_condition, boost::system::error_code& ec,
69 is_mutable_buffer_sequence<MutableBufferSequence>::value
72 return detail::read_buffer_sequence(s, buffers,
73 boost::asio::buffer_sequence_begin(buffers),
74 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
77 template <typename SyncReadStream, typename MutableBufferSequence>
78 inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
80 is_mutable_buffer_sequence<MutableBufferSequence>::value
83 boost::system::error_code ec;
84 std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
85 boost::asio::detail::throw_error(ec, "read");
86 return bytes_transferred;
89 template <typename SyncReadStream, typename MutableBufferSequence>
90 inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
91 boost::system::error_code& ec,
93 is_mutable_buffer_sequence<MutableBufferSequence>::value
96 return read(s, buffers, transfer_all(), ec);
99 template <typename SyncReadStream, typename MutableBufferSequence,
100 typename CompletionCondition>
101 inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
102 CompletionCondition completion_condition,
104 is_mutable_buffer_sequence<MutableBufferSequence>::value
107 boost::system::error_code ec;
108 std::size_t bytes_transferred = read(s, buffers,
109 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
110 boost::asio::detail::throw_error(ec, "read");
111 return bytes_transferred;
114 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
116 template <typename SyncReadStream, typename DynamicBuffer_v1,
117 typename CompletionCondition>
118 std::size_t read(SyncReadStream& s,
119 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
120 CompletionCondition completion_condition, boost::system::error_code& ec,
122 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
123 && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
126 typename decay<DynamicBuffer_v1>::type b(
127 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
129 ec = boost::system::error_code();
130 std::size_t total_transferred = 0;
131 std::size_t max_size = detail::adapt_completion_condition_result(
132 completion_condition(ec, total_transferred));
133 std::size_t bytes_available = std::min<std::size_t>(
134 std::max<std::size_t>(512, b.capacity() - b.size()),
135 std::min<std::size_t>(max_size, b.max_size() - b.size()));
136 while (bytes_available > 0)
138 std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
139 b.commit(bytes_transferred);
140 total_transferred += bytes_transferred;
141 max_size = detail::adapt_completion_condition_result(
142 completion_condition(ec, total_transferred));
143 bytes_available = std::min<std::size_t>(
144 std::max<std::size_t>(512, b.capacity() - b.size()),
145 std::min<std::size_t>(max_size, b.max_size() - b.size()));
147 return total_transferred;
150 template <typename SyncReadStream, typename DynamicBuffer_v1>
151 inline std::size_t read(SyncReadStream& s,
152 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
154 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
155 && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
158 boost::system::error_code ec;
159 std::size_t bytes_transferred = read(s,
160 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), transfer_all(), ec);
161 boost::asio::detail::throw_error(ec, "read");
162 return bytes_transferred;
165 template <typename SyncReadStream, typename DynamicBuffer_v1>
166 inline std::size_t read(SyncReadStream& s,
167 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
168 boost::system::error_code& ec,
170 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
171 && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
174 return read(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
178 template <typename SyncReadStream, typename DynamicBuffer_v1,
179 typename CompletionCondition>
180 inline std::size_t read(SyncReadStream& s,
181 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
182 CompletionCondition completion_condition,
184 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
185 && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
188 boost::system::error_code ec;
189 std::size_t bytes_transferred = read(s,
190 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
191 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
192 boost::asio::detail::throw_error(ec, "read");
193 return bytes_transferred;
196 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
197 #if !defined(BOOST_ASIO_NO_IOSTREAM)
199 template <typename SyncReadStream, typename Allocator,
200 typename CompletionCondition>
201 inline std::size_t read(SyncReadStream& s,
202 boost::asio::basic_streambuf<Allocator>& b,
203 CompletionCondition completion_condition, boost::system::error_code& ec)
205 return read(s, basic_streambuf_ref<Allocator>(b),
206 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
209 template <typename SyncReadStream, typename Allocator>
210 inline std::size_t read(SyncReadStream& s,
211 boost::asio::basic_streambuf<Allocator>& b)
213 return read(s, basic_streambuf_ref<Allocator>(b));
216 template <typename SyncReadStream, typename Allocator>
217 inline std::size_t read(SyncReadStream& s,
218 boost::asio::basic_streambuf<Allocator>& b,
219 boost::system::error_code& ec)
221 return read(s, basic_streambuf_ref<Allocator>(b), ec);
224 template <typename SyncReadStream, typename Allocator,
225 typename CompletionCondition>
226 inline std::size_t read(SyncReadStream& s,
227 boost::asio::basic_streambuf<Allocator>& b,
228 CompletionCondition completion_condition)
230 return read(s, basic_streambuf_ref<Allocator>(b),
231 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
234 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
235 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
236 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
238 template <typename SyncReadStream, typename DynamicBuffer_v2,
239 typename CompletionCondition>
240 std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
241 CompletionCondition completion_condition, boost::system::error_code& ec,
243 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
246 DynamicBuffer_v2& b = buffers;
248 ec = boost::system::error_code();
249 std::size_t total_transferred = 0;
250 std::size_t max_size = detail::adapt_completion_condition_result(
251 completion_condition(ec, total_transferred));
252 std::size_t bytes_available = std::min<std::size_t>(
253 std::max<std::size_t>(512, b.capacity() - b.size()),
254 std::min<std::size_t>(max_size, b.max_size() - b.size()));
255 while (bytes_available > 0)
257 std::size_t pos = b.size();
258 b.grow(bytes_available);
259 std::size_t bytes_transferred = s.read_some(
260 b.data(pos, bytes_available), ec);
261 b.shrink(bytes_available - bytes_transferred);
262 total_transferred += bytes_transferred;
263 max_size = detail::adapt_completion_condition_result(
264 completion_condition(ec, total_transferred));
265 bytes_available = std::min<std::size_t>(
266 std::max<std::size_t>(512, b.capacity() - b.size()),
267 std::min<std::size_t>(max_size, b.max_size() - b.size()));
269 return total_transferred;
272 template <typename SyncReadStream, typename DynamicBuffer_v2>
273 inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
275 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
278 boost::system::error_code ec;
279 std::size_t bytes_transferred = read(s,
280 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), transfer_all(), ec);
281 boost::asio::detail::throw_error(ec, "read");
282 return bytes_transferred;
285 template <typename SyncReadStream, typename DynamicBuffer_v2>
286 inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
287 boost::system::error_code& ec,
289 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
292 return read(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
296 template <typename SyncReadStream, typename DynamicBuffer_v2,
297 typename CompletionCondition>
298 inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
299 CompletionCondition completion_condition,
301 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
304 boost::system::error_code ec;
305 std::size_t bytes_transferred = read(s,
306 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
307 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
308 boost::asio::detail::throw_error(ec, "read");
309 return bytes_transferred;
314 template <typename AsyncReadStream, typename MutableBufferSequence,
315 typename MutableBufferIterator, typename CompletionCondition,
316 typename ReadHandler>
318 : detail::base_from_completion_cond<CompletionCondition>
321 read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers,
322 CompletionCondition& completion_condition, ReadHandler& handler)
323 : detail::base_from_completion_cond<
324 CompletionCondition>(completion_condition),
328 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
332 #if defined(BOOST_ASIO_HAS_MOVE)
333 read_op(const read_op& other)
334 : detail::base_from_completion_cond<CompletionCondition>(other),
335 stream_(other.stream_),
336 buffers_(other.buffers_),
337 start_(other.start_),
338 handler_(other.handler_)
342 read_op(read_op&& other)
343 : detail::base_from_completion_cond<CompletionCondition>(
344 BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
345 CompletionCondition>)(other)),
346 stream_(other.stream_),
347 buffers_(BOOST_ASIO_MOVE_CAST(buffers_type)(other.buffers_)),
348 start_(other.start_),
349 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
352 #endif // defined(BOOST_ASIO_HAS_MOVE)
354 void operator()(const boost::system::error_code& ec,
355 std::size_t bytes_transferred, int start = 0)
357 std::size_t max_size;
358 switch (start_ = start)
361 max_size = this->check_for_completion(ec, buffers_.total_consumed());
364 stream_.async_read_some(buffers_.prepare(max_size),
365 BOOST_ASIO_MOVE_CAST(read_op)(*this));
367 buffers_.consume(bytes_transferred);
368 if ((!ec && bytes_transferred == 0) || buffers_.empty())
370 max_size = this->check_for_completion(ec, buffers_.total_consumed());
371 } while (max_size > 0);
373 handler_(ec, buffers_.total_consumed());
378 typedef boost::asio::detail::consuming_buffers<mutable_buffer,
379 MutableBufferSequence, MutableBufferIterator> buffers_type;
381 AsyncReadStream& stream_;
382 buffers_type buffers_;
384 ReadHandler handler_;
387 template <typename AsyncReadStream, typename MutableBufferSequence,
388 typename MutableBufferIterator, typename CompletionCondition,
389 typename ReadHandler>
390 inline void* asio_handler_allocate(std::size_t size,
391 read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
392 CompletionCondition, ReadHandler>* this_handler)
394 return boost_asio_handler_alloc_helpers::allocate(
395 size, this_handler->handler_);
398 template <typename AsyncReadStream, typename MutableBufferSequence,
399 typename MutableBufferIterator, typename CompletionCondition,
400 typename ReadHandler>
401 inline void asio_handler_deallocate(void* pointer, std::size_t size,
402 read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
403 CompletionCondition, ReadHandler>* this_handler)
405 boost_asio_handler_alloc_helpers::deallocate(
406 pointer, size, this_handler->handler_);
409 template <typename AsyncReadStream, typename MutableBufferSequence,
410 typename MutableBufferIterator, typename CompletionCondition,
411 typename ReadHandler>
412 inline bool asio_handler_is_continuation(
413 read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
414 CompletionCondition, ReadHandler>* this_handler)
416 return this_handler->start_ == 0 ? true
417 : boost_asio_handler_cont_helpers::is_continuation(
418 this_handler->handler_);
421 template <typename Function, typename AsyncReadStream,
422 typename MutableBufferSequence, typename MutableBufferIterator,
423 typename CompletionCondition, typename ReadHandler>
424 inline void asio_handler_invoke(Function& function,
425 read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
426 CompletionCondition, ReadHandler>* this_handler)
428 boost_asio_handler_invoke_helpers::invoke(
429 function, this_handler->handler_);
432 template <typename Function, typename AsyncReadStream,
433 typename MutableBufferSequence, typename MutableBufferIterator,
434 typename CompletionCondition, typename ReadHandler>
435 inline void asio_handler_invoke(const Function& function,
436 read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
437 CompletionCondition, ReadHandler>* this_handler)
439 boost_asio_handler_invoke_helpers::invoke(
440 function, this_handler->handler_);
443 template <typename AsyncReadStream, typename MutableBufferSequence,
444 typename MutableBufferIterator, typename CompletionCondition,
445 typename ReadHandler>
446 inline void start_read_buffer_sequence_op(AsyncReadStream& stream,
447 const MutableBufferSequence& buffers, const MutableBufferIterator&,
448 CompletionCondition& completion_condition, ReadHandler& handler)
450 detail::read_op<AsyncReadStream, MutableBufferSequence,
451 MutableBufferIterator, CompletionCondition, ReadHandler>(
452 stream, buffers, completion_condition, handler)(
453 boost::system::error_code(), 0, 1);
456 template <typename AsyncReadStream>
457 class initiate_async_read_buffer_sequence
460 typedef typename AsyncReadStream::executor_type executor_type;
462 explicit initiate_async_read_buffer_sequence(AsyncReadStream& stream)
467 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
469 return stream_.get_executor();
472 template <typename ReadHandler, typename MutableBufferSequence,
473 typename CompletionCondition>
474 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
475 const MutableBufferSequence& buffers,
476 BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
478 // If you get an error on the following line it means that your handler
479 // does not meet the documented type requirements for a ReadHandler.
480 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
482 non_const_lvalue<ReadHandler> handler2(handler);
483 non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
484 start_read_buffer_sequence_op(stream_, buffers,
485 boost::asio::buffer_sequence_begin(buffers),
486 completion_cond2.value, handler2.value);
490 AsyncReadStream& stream_;
492 } // namespace detail
494 #if !defined(GENERATING_DOCUMENTATION)
496 template <typename AsyncReadStream, typename MutableBufferSequence,
497 typename MutableBufferIterator, typename CompletionCondition,
498 typename ReadHandler, typename Allocator>
499 struct associated_allocator<
500 detail::read_op<AsyncReadStream, MutableBufferSequence,
501 MutableBufferIterator, CompletionCondition, ReadHandler>,
504 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
507 const detail::read_op<AsyncReadStream, MutableBufferSequence,
508 MutableBufferIterator, CompletionCondition, ReadHandler>& h,
509 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
511 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
515 template <typename AsyncReadStream, typename MutableBufferSequence,
516 typename MutableBufferIterator, typename CompletionCondition,
517 typename ReadHandler, typename Executor>
518 struct associated_executor<
519 detail::read_op<AsyncReadStream, MutableBufferSequence,
520 MutableBufferIterator, CompletionCondition, ReadHandler>,
523 typedef typename associated_executor<ReadHandler, Executor>::type type;
526 const detail::read_op<AsyncReadStream, MutableBufferSequence,
527 MutableBufferIterator, CompletionCondition, ReadHandler>& h,
528 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
530 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
534 #endif // !defined(GENERATING_DOCUMENTATION)
536 template <typename AsyncReadStream,
537 typename MutableBufferSequence, typename CompletionCondition,
538 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
539 std::size_t)) ReadHandler>
540 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
541 void (boost::system::error_code, std::size_t))
542 async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
543 CompletionCondition completion_condition,
544 BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
546 is_mutable_buffer_sequence<MutableBufferSequence>::value
549 return async_initiate<ReadHandler,
550 void (boost::system::error_code, std::size_t)>(
551 detail::initiate_async_read_buffer_sequence<AsyncReadStream>(s), handler,
552 buffers, BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
555 template <typename AsyncReadStream, typename MutableBufferSequence,
556 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
557 std::size_t)) ReadHandler>
558 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
559 void (boost::system::error_code, std::size_t))
560 async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
561 BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
563 is_mutable_buffer_sequence<MutableBufferSequence>::value
566 return async_initiate<ReadHandler,
567 void (boost::system::error_code, std::size_t)>(
568 detail::initiate_async_read_buffer_sequence<AsyncReadStream>(s),
569 handler, buffers, transfer_all());
572 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
576 template <typename AsyncReadStream, typename DynamicBuffer_v1,
577 typename CompletionCondition, typename ReadHandler>
578 class read_dynbuf_v1_op
579 : detail::base_from_completion_cond<CompletionCondition>
582 template <typename BufferSequence>
583 read_dynbuf_v1_op(AsyncReadStream& stream,
584 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
585 CompletionCondition& completion_condition, ReadHandler& handler)
586 : detail::base_from_completion_cond<
587 CompletionCondition>(completion_condition),
589 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
591 total_transferred_(0),
592 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
596 #if defined(BOOST_ASIO_HAS_MOVE)
597 read_dynbuf_v1_op(const read_dynbuf_v1_op& other)
598 : detail::base_from_completion_cond<CompletionCondition>(other),
599 stream_(other.stream_),
600 buffers_(other.buffers_),
601 start_(other.start_),
602 total_transferred_(other.total_transferred_),
603 handler_(other.handler_)
607 read_dynbuf_v1_op(read_dynbuf_v1_op&& other)
608 : detail::base_from_completion_cond<CompletionCondition>(
609 BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
610 CompletionCondition>)(other)),
611 stream_(other.stream_),
612 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
613 start_(other.start_),
614 total_transferred_(other.total_transferred_),
615 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
618 #endif // defined(BOOST_ASIO_HAS_MOVE)
620 void operator()(const boost::system::error_code& ec,
621 std::size_t bytes_transferred, int start = 0)
623 std::size_t max_size, bytes_available;
624 switch (start_ = start)
627 max_size = this->check_for_completion(ec, total_transferred_);
628 bytes_available = std::min<std::size_t>(
629 std::max<std::size_t>(512,
630 buffers_.capacity() - buffers_.size()),
631 std::min<std::size_t>(max_size,
632 buffers_.max_size() - buffers_.size()));
635 stream_.async_read_some(buffers_.prepare(bytes_available),
636 BOOST_ASIO_MOVE_CAST(read_dynbuf_v1_op)(*this));
638 total_transferred_ += bytes_transferred;
639 buffers_.commit(bytes_transferred);
640 max_size = this->check_for_completion(ec, total_transferred_);
641 bytes_available = std::min<std::size_t>(
642 std::max<std::size_t>(512,
643 buffers_.capacity() - buffers_.size()),
644 std::min<std::size_t>(max_size,
645 buffers_.max_size() - buffers_.size()));
646 if ((!ec && bytes_transferred == 0) || bytes_available == 0)
650 handler_(ec, static_cast<const std::size_t&>(total_transferred_));
655 AsyncReadStream& stream_;
656 DynamicBuffer_v1 buffers_;
658 std::size_t total_transferred_;
659 ReadHandler handler_;
662 template <typename AsyncReadStream, typename DynamicBuffer_v1,
663 typename CompletionCondition, typename ReadHandler>
664 inline void* asio_handler_allocate(std::size_t size,
665 read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
666 CompletionCondition, ReadHandler>* this_handler)
668 return boost_asio_handler_alloc_helpers::allocate(
669 size, this_handler->handler_);
672 template <typename AsyncReadStream, typename DynamicBuffer_v1,
673 typename CompletionCondition, typename ReadHandler>
674 inline void asio_handler_deallocate(void* pointer, std::size_t size,
675 read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
676 CompletionCondition, ReadHandler>* this_handler)
678 boost_asio_handler_alloc_helpers::deallocate(
679 pointer, size, this_handler->handler_);
682 template <typename AsyncReadStream, typename DynamicBuffer_v1,
683 typename CompletionCondition, typename ReadHandler>
684 inline bool asio_handler_is_continuation(
685 read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
686 CompletionCondition, ReadHandler>* this_handler)
688 return this_handler->start_ == 0 ? true
689 : boost_asio_handler_cont_helpers::is_continuation(
690 this_handler->handler_);
693 template <typename Function, typename AsyncReadStream,
694 typename DynamicBuffer_v1, typename CompletionCondition,
695 typename ReadHandler>
696 inline void asio_handler_invoke(Function& function,
697 read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
698 CompletionCondition, ReadHandler>* this_handler)
700 boost_asio_handler_invoke_helpers::invoke(
701 function, this_handler->handler_);
704 template <typename Function, typename AsyncReadStream,
705 typename DynamicBuffer_v1, typename CompletionCondition,
706 typename ReadHandler>
707 inline void asio_handler_invoke(const Function& function,
708 read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
709 CompletionCondition, ReadHandler>* this_handler)
711 boost_asio_handler_invoke_helpers::invoke(
712 function, this_handler->handler_);
715 template <typename AsyncReadStream>
716 class initiate_async_read_dynbuf_v1
719 typedef typename AsyncReadStream::executor_type executor_type;
721 explicit initiate_async_read_dynbuf_v1(AsyncReadStream& stream)
726 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
728 return stream_.get_executor();
731 template <typename ReadHandler, typename DynamicBuffer_v1,
732 typename CompletionCondition>
733 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
734 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
735 BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
737 // If you get an error on the following line it means that your handler
738 // does not meet the documented type requirements for a ReadHandler.
739 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
741 non_const_lvalue<ReadHandler> handler2(handler);
742 non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
743 read_dynbuf_v1_op<AsyncReadStream, typename decay<DynamicBuffer_v1>::type,
744 CompletionCondition, typename decay<ReadHandler>::type>(
745 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
746 completion_cond2.value, handler2.value)(
747 boost::system::error_code(), 0, 1);
751 AsyncReadStream& stream_;
753 } // namespace detail
755 #if !defined(GENERATING_DOCUMENTATION)
757 template <typename AsyncReadStream, typename DynamicBuffer_v1,
758 typename CompletionCondition, typename ReadHandler, typename Allocator>
759 struct associated_allocator<
760 detail::read_dynbuf_v1_op<AsyncReadStream,
761 DynamicBuffer_v1, CompletionCondition, ReadHandler>,
764 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
767 const detail::read_dynbuf_v1_op<AsyncReadStream,
768 DynamicBuffer_v1, CompletionCondition, ReadHandler>& h,
769 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
771 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
775 template <typename AsyncReadStream, typename DynamicBuffer_v1,
776 typename CompletionCondition, typename ReadHandler, typename Executor>
777 struct associated_executor<
778 detail::read_dynbuf_v1_op<AsyncReadStream,
779 DynamicBuffer_v1, CompletionCondition, ReadHandler>,
782 typedef typename associated_executor<ReadHandler, Executor>::type type;
785 const detail::read_dynbuf_v1_op<AsyncReadStream,
786 DynamicBuffer_v1, CompletionCondition, ReadHandler>& h,
787 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
789 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
793 #endif // !defined(GENERATING_DOCUMENTATION)
795 template <typename AsyncReadStream, typename DynamicBuffer_v1,
796 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
797 std::size_t)) ReadHandler>
798 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
799 void (boost::system::error_code, std::size_t))
800 async_read(AsyncReadStream& s,
801 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
802 BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
804 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
805 && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
809 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
810 transfer_all(), BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
813 template <typename AsyncReadStream,
814 typename DynamicBuffer_v1, typename CompletionCondition,
815 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
816 std::size_t)) ReadHandler>
817 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
818 void (boost::system::error_code, std::size_t))
819 async_read(AsyncReadStream& s,
820 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
821 CompletionCondition completion_condition,
822 BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
824 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
825 && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
828 // If you get an error on the following line it means that your handler does
829 // not meet the documented type requirements for a ReadHandler.
830 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
832 return async_initiate<ReadHandler,
833 void (boost::system::error_code, std::size_t)>(
834 detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s),
835 handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
836 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
839 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
840 #if !defined(BOOST_ASIO_NO_IOSTREAM)
842 template <typename AsyncReadStream, typename Allocator,
843 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
844 std::size_t)) ReadHandler>
845 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
846 void (boost::system::error_code, std::size_t))
847 async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
848 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
850 return async_read(s, basic_streambuf_ref<Allocator>(b),
851 BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
854 template <typename AsyncReadStream,
855 typename Allocator, typename CompletionCondition,
856 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
857 std::size_t)) ReadHandler>
858 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
859 void (boost::system::error_code, std::size_t))
860 async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
861 CompletionCondition completion_condition,
862 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
864 return async_read(s, basic_streambuf_ref<Allocator>(b),
865 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition),
866 BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
869 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
870 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
871 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
875 template <typename AsyncReadStream, typename DynamicBuffer_v2,
876 typename CompletionCondition, typename ReadHandler>
877 class read_dynbuf_v2_op
878 : detail::base_from_completion_cond<CompletionCondition>
881 template <typename BufferSequence>
882 read_dynbuf_v2_op(AsyncReadStream& stream,
883 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
884 CompletionCondition& completion_condition, ReadHandler& handler)
885 : detail::base_from_completion_cond<
886 CompletionCondition>(completion_condition),
888 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
890 total_transferred_(0),
892 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
896 #if defined(BOOST_ASIO_HAS_MOVE)
897 read_dynbuf_v2_op(const read_dynbuf_v2_op& other)
898 : detail::base_from_completion_cond<CompletionCondition>(other),
899 stream_(other.stream_),
900 buffers_(other.buffers_),
901 start_(other.start_),
902 total_transferred_(other.total_transferred_),
903 bytes_available_(other.bytes_available_),
904 handler_(other.handler_)
908 read_dynbuf_v2_op(read_dynbuf_v2_op&& other)
909 : detail::base_from_completion_cond<CompletionCondition>(
910 BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
911 CompletionCondition>)(other)),
912 stream_(other.stream_),
913 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
914 start_(other.start_),
915 total_transferred_(other.total_transferred_),
916 bytes_available_(other.bytes_available_),
917 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
920 #endif // defined(BOOST_ASIO_HAS_MOVE)
922 void operator()(const boost::system::error_code& ec,
923 std::size_t bytes_transferred, int start = 0)
925 std::size_t max_size, pos;
926 switch (start_ = start)
929 max_size = this->check_for_completion(ec, total_transferred_);
930 bytes_available_ = std::min<std::size_t>(
931 std::max<std::size_t>(512,
932 buffers_.capacity() - buffers_.size()),
933 std::min<std::size_t>(max_size,
934 buffers_.max_size() - buffers_.size()));
937 pos = buffers_.size();
938 buffers_.grow(bytes_available_);
939 stream_.async_read_some(buffers_.data(pos, bytes_available_),
940 BOOST_ASIO_MOVE_CAST(read_dynbuf_v2_op)(*this));
942 total_transferred_ += bytes_transferred;
943 buffers_.shrink(bytes_available_ - bytes_transferred);
944 max_size = this->check_for_completion(ec, total_transferred_);
945 bytes_available_ = std::min<std::size_t>(
946 std::max<std::size_t>(512,
947 buffers_.capacity() - buffers_.size()),
948 std::min<std::size_t>(max_size,
949 buffers_.max_size() - buffers_.size()));
950 if ((!ec && bytes_transferred == 0) || bytes_available_ == 0)
954 handler_(ec, static_cast<const std::size_t&>(total_transferred_));
959 AsyncReadStream& stream_;
960 DynamicBuffer_v2 buffers_;
962 std::size_t total_transferred_;
963 std::size_t bytes_available_;
964 ReadHandler handler_;
967 template <typename AsyncReadStream, typename DynamicBuffer_v2,
968 typename CompletionCondition, typename ReadHandler>
969 inline void* asio_handler_allocate(std::size_t size,
970 read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
971 CompletionCondition, ReadHandler>* this_handler)
973 return boost_asio_handler_alloc_helpers::allocate(
974 size, this_handler->handler_);
977 template <typename AsyncReadStream, typename DynamicBuffer_v2,
978 typename CompletionCondition, typename ReadHandler>
979 inline void asio_handler_deallocate(void* pointer, std::size_t size,
980 read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
981 CompletionCondition, ReadHandler>* this_handler)
983 boost_asio_handler_alloc_helpers::deallocate(
984 pointer, size, this_handler->handler_);
987 template <typename AsyncReadStream, typename DynamicBuffer_v2,
988 typename CompletionCondition, typename ReadHandler>
989 inline bool asio_handler_is_continuation(
990 read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
991 CompletionCondition, ReadHandler>* this_handler)
993 return this_handler->start_ == 0 ? true
994 : boost_asio_handler_cont_helpers::is_continuation(
995 this_handler->handler_);
998 template <typename Function, typename AsyncReadStream,
999 typename DynamicBuffer_v2, typename CompletionCondition,
1000 typename ReadHandler>
1001 inline void asio_handler_invoke(Function& function,
1002 read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
1003 CompletionCondition, ReadHandler>* this_handler)
1005 boost_asio_handler_invoke_helpers::invoke(
1006 function, this_handler->handler_);
1009 template <typename Function, typename AsyncReadStream,
1010 typename DynamicBuffer_v2, typename CompletionCondition,
1011 typename ReadHandler>
1012 inline void asio_handler_invoke(const Function& function,
1013 read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
1014 CompletionCondition, ReadHandler>* this_handler)
1016 boost_asio_handler_invoke_helpers::invoke(
1017 function, this_handler->handler_);
1020 template <typename AsyncReadStream>
1021 class initiate_async_read_dynbuf_v2
1024 typedef typename AsyncReadStream::executor_type executor_type;
1026 explicit initiate_async_read_dynbuf_v2(AsyncReadStream& stream)
1031 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
1033 return stream_.get_executor();
1036 template <typename ReadHandler, typename DynamicBuffer_v2,
1037 typename CompletionCondition>
1038 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1039 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
1040 BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
1042 // If you get an error on the following line it means that your handler
1043 // does not meet the documented type requirements for a ReadHandler.
1044 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1046 non_const_lvalue<ReadHandler> handler2(handler);
1047 non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
1048 read_dynbuf_v2_op<AsyncReadStream, typename decay<DynamicBuffer_v2>::type,
1049 CompletionCondition, typename decay<ReadHandler>::type>(
1050 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
1051 completion_cond2.value, handler2.value)(
1052 boost::system::error_code(), 0, 1);
1056 AsyncReadStream& stream_;
1058 } // namespace detail
1060 #if !defined(GENERATING_DOCUMENTATION)
1062 template <typename AsyncReadStream, typename DynamicBuffer_v2,
1063 typename CompletionCondition, typename ReadHandler, typename Allocator>
1064 struct associated_allocator<
1065 detail::read_dynbuf_v2_op<AsyncReadStream,
1066 DynamicBuffer_v2, CompletionCondition, ReadHandler>,
1069 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
1072 const detail::read_dynbuf_v2_op<AsyncReadStream,
1073 DynamicBuffer_v2, CompletionCondition, ReadHandler>& h,
1074 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
1076 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
1080 template <typename AsyncReadStream, typename DynamicBuffer_v2,
1081 typename CompletionCondition, typename ReadHandler, typename Executor>
1082 struct associated_executor<
1083 detail::read_dynbuf_v2_op<AsyncReadStream,
1084 DynamicBuffer_v2, CompletionCondition, ReadHandler>,
1087 typedef typename associated_executor<ReadHandler, Executor>::type type;
1090 const detail::read_dynbuf_v2_op<AsyncReadStream,
1091 DynamicBuffer_v2, CompletionCondition, ReadHandler>& h,
1092 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
1094 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
1098 #endif // !defined(GENERATING_DOCUMENTATION)
1100 template <typename AsyncReadStream, typename DynamicBuffer_v2,
1101 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1102 std::size_t)) ReadHandler>
1103 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
1104 void (boost::system::error_code, std::size_t))
1105 async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,
1106 BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1108 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
1111 return async_read(s,
1112 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
1113 transfer_all(), BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
1116 template <typename AsyncReadStream,
1117 typename DynamicBuffer_v2, typename CompletionCondition,
1118 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1119 std::size_t)) ReadHandler>
1120 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
1121 void (boost::system::error_code, std::size_t))
1122 async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,
1123 CompletionCondition completion_condition,
1124 BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1126 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
1129 // If you get an error on the following line it means that your handler does
1130 // not meet the documented type requirements for a ReadHandler.
1131 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1133 return async_initiate<ReadHandler,
1134 void (boost::system::error_code, std::size_t)>(
1135 detail::initiate_async_read_dynbuf_v2<AsyncReadStream>(s),
1136 handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
1137 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
1141 } // namespace boost
1143 #include <boost/asio/detail/pop_options.hpp>
1145 #endif // BOOST_ASIO_IMPL_READ_HPP