1//
2// impl/read.hpp
3// ~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6//
7// Distributed under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9//
10
11#ifndef BOOST_ASIO_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/buffer.hpp>
20#include <boost/asio/completion_condition.hpp>
21#include <boost/asio/detail/array_fwd.hpp>
22#include <boost/asio/detail/base_from_completion_cond.hpp>
23#include <boost/asio/detail/bind_handler.hpp>
24#include <boost/asio/detail/consuming_buffers.hpp>
25#include <boost/asio/detail/dependent_type.hpp>
26#include <boost/asio/detail/handler_alloc_helpers.hpp>
27#include <boost/asio/detail/handler_cont_helpers.hpp>
28#include <boost/asio/detail/handler_invoke_helpers.hpp>
29#include <boost/asio/detail/handler_type_requirements.hpp>
30#include <boost/asio/detail/throw_error.hpp>
31#include <boost/asio/error.hpp>
32
33#include <boost/asio/detail/push_options.hpp>
34
35namespace boost {
36namespace asio {
37
38template <typename SyncReadStream, typename MutableBufferSequence,
39 typename CompletionCondition>
40std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
41 CompletionCondition completion_condition, boost::system::error_code& ec)
42{
43 ec = boost::system::error_code();
44 boost::asio::detail::consuming_buffers<
45 mutable_buffer, MutableBufferSequence> tmp(buffers);
46 std::size_t total_transferred = 0;
47 tmp.prepare(detail::adapt_completion_condition_result(
48 completion_condition(ec, total_transferred)));
49 while (tmp.begin() != tmp.end())
50 {
51 std::size_t bytes_transferred = s.read_some(tmp, ec);
52 tmp.consume(bytes_transferred);
53 total_transferred += bytes_transferred;
54 tmp.prepare(detail::adapt_completion_condition_result(
55 completion_condition(ec, total_transferred)));
56 }
57 return total_transferred;
58}
59
60template <typename SyncReadStream, typename MutableBufferSequence>
61inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers)
62{
63 boost::system::error_code ec;
64 std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
65 boost::asio::detail::throw_error(ec, "read");
66 return bytes_transferred;
67}
68
69template <typename SyncReadStream, typename MutableBufferSequence>
70inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
71 boost::system::error_code& ec)
72{
73 return read(s, buffers, transfer_all(), ec);
74}
75
76template <typename SyncReadStream, typename MutableBufferSequence,
77 typename CompletionCondition>
78inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
79 CompletionCondition completion_condition)
80{
81 boost::system::error_code ec;
82 std::size_t bytes_transferred = read(s, buffers, completion_condition, ec);
83 boost::asio::detail::throw_error(ec, "read");
84 return bytes_transferred;
85}
86
87#if !defined(BOOST_ASIO_NO_IOSTREAM)
88
89template <typename SyncReadStream, typename Allocator,
90 typename CompletionCondition>
91std::size_t read(SyncReadStream& s,
92 boost::asio::basic_streambuf<Allocator>& b,
93 CompletionCondition completion_condition, boost::system::error_code& ec)
94{
95 ec = boost::system::error_code();
96 std::size_t total_transferred = 0;
97 std::size_t max_size = detail::adapt_completion_condition_result(
98 completion_condition(ec, total_transferred));
99 std::size_t bytes_available = read_size_helper(b, max_size);
100 while (bytes_available > 0)
101 {
102 std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
103 b.commit(bytes_transferred);
104 total_transferred += bytes_transferred;
105 max_size = detail::adapt_completion_condition_result(
106 completion_condition(ec, total_transferred));
107 bytes_available = read_size_helper(b, max_size);
108 }
109 return total_transferred;
110}
111
112template <typename SyncReadStream, typename Allocator>
113inline std::size_t read(SyncReadStream& s,
114 boost::asio::basic_streambuf<Allocator>& b)
115{
116 boost::system::error_code ec;
117 std::size_t bytes_transferred = read(s, b, transfer_all(), ec);
118 boost::asio::detail::throw_error(ec, "read");
119 return bytes_transferred;
120}
121
122template <typename SyncReadStream, typename Allocator>
123inline std::size_t read(SyncReadStream& s,
124 boost::asio::basic_streambuf<Allocator>& b,
125 boost::system::error_code& ec)
126{
127 return read(s, b, transfer_all(), ec);
128}
129
130template <typename SyncReadStream, typename Allocator,
131 typename CompletionCondition>
132inline std::size_t read(SyncReadStream& s,
133 boost::asio::basic_streambuf<Allocator>& b,
134 CompletionCondition completion_condition)
135{
136 boost::system::error_code ec;
137 std::size_t bytes_transferred = read(s, b, completion_condition, ec);
138 boost::asio::detail::throw_error(ec, "read");
139 return bytes_transferred;
140}
141
142#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
143
144namespace detail
145{
146 template <typename AsyncReadStream, typename MutableBufferSequence,
147 typename CompletionCondition, typename ReadHandler>
148 class read_op
149 : detail::base_from_completion_cond<CompletionCondition>
150 {
151 public:
152 read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers,
153 CompletionCondition completion_condition, ReadHandler& handler)
154 : detail::base_from_completion_cond<
155 CompletionCondition>(completion_condition),
156 stream_(stream),
157 buffers_(buffers),
158 start_(0),
159 total_transferred_(0),
160 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
161 {
162 }
163
164#if defined(BOOST_ASIO_HAS_MOVE)
165 read_op(const read_op& other)
166 : detail::base_from_completion_cond<CompletionCondition>(other),
167 stream_(other.stream_),
168 buffers_(other.buffers_),
169 start_(other.start_),
170 total_transferred_(other.total_transferred_),
171 handler_(other.handler_)
172 {
173 }
174
175 read_op(read_op&& other)
176 : detail::base_from_completion_cond<CompletionCondition>(other),
177 stream_(other.stream_),
178 buffers_(other.buffers_),
179 start_(other.start_),
180 total_transferred_(other.total_transferred_),
181 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
182 {
183 }
184#endif // defined(BOOST_ASIO_HAS_MOVE)
185
186 void operator()(const boost::system::error_code& ec,
187 std::size_t bytes_transferred, int start = 0)
188 {
189 switch (start_ = start)
190 {
191 case 1:
192 buffers_.prepare(this->check_for_completion(ec, total_transferred_));
193 for (;;)
194 {
195 stream_.async_read_some(buffers_,
196 BOOST_ASIO_MOVE_CAST(read_op)(*this));
197 return; default:
198 total_transferred_ += bytes_transferred;
199 buffers_.consume(bytes_transferred);
200 buffers_.prepare(this->check_for_completion(ec, total_transferred_));
201 if ((!ec && bytes_transferred == 0)
202 || buffers_.begin() == buffers_.end())
203 break;
204 }
205
206 handler_(ec, static_cast<const std::size_t&>(total_transferred_));
207 }
208 }
209
210 //private:
211 AsyncReadStream& stream_;
212 boost::asio::detail::consuming_buffers<
213 mutable_buffer, MutableBufferSequence> buffers_;
214 int start_;
215 std::size_t total_transferred_;
216 ReadHandler handler_;
217 };
218
219 template <typename AsyncReadStream,
220 typename CompletionCondition, typename ReadHandler>
221 class read_op<AsyncReadStream, boost::asio::mutable_buffers_1,
222 CompletionCondition, ReadHandler>
223 : detail::base_from_completion_cond<CompletionCondition>
224 {
225 public:
226 read_op(AsyncReadStream& stream,
227 const boost::asio::mutable_buffers_1& buffers,
228 CompletionCondition completion_condition, ReadHandler& handler)
229 : detail::base_from_completion_cond<
230 CompletionCondition>(completion_condition),
231 stream_(stream),
232 buffer_(buffers),
233 start_(0),
234 total_transferred_(0),
235 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
236 {
237 }
238
239#if defined(BOOST_ASIO_HAS_MOVE)
240 read_op(const read_op& other)
241 : detail::base_from_completion_cond<CompletionCondition>(other),
242 stream_(other.stream_),
243 buffer_(other.buffer_),
244 start_(other.start_),
245 total_transferred_(other.total_transferred_),
246 handler_(other.handler_)
247 {
248 }
249
250 read_op(read_op&& other)
251 : detail::base_from_completion_cond<CompletionCondition>(other),
252 stream_(other.stream_),
253 buffer_(other.buffer_),
254 start_(other.start_),
255 total_transferred_(other.total_transferred_),
256 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
257 {
258 }
259#endif // defined(BOOST_ASIO_HAS_MOVE)
260
261 void operator()(const boost::system::error_code& ec,
262 std::size_t bytes_transferred, int start = 0)
263 {
264 std::size_t n = 0;
265 switch (start_ = start)
266 {
267 case 1:
268 n = this->check_for_completion(ec, total_transferred_);
269 for (;;)
270 {
271 stream_.async_read_some(
272 boost::asio::buffer(buffer_ + total_transferred_, n),
273 BOOST_ASIO_MOVE_CAST(read_op)(*this));
274 return; default:
275 total_transferred_ += bytes_transferred;
276 if ((!ec && bytes_transferred == 0)
277 || (n = this->check_for_completion(ec, total_transferred_)) == 0
278 || total_transferred_ == boost::asio::buffer_size(buffer_))
279 break;
280 }
281
282 handler_(ec, static_cast<const std::size_t&>(total_transferred_));
283 }
284 }
285
286 //private:
287 AsyncReadStream& stream_;
288 boost::asio::mutable_buffer buffer_;
289 int start_;
290 std::size_t total_transferred_;
291 ReadHandler handler_;
292 };
293
294 template <typename AsyncReadStream, typename Elem,
295 typename CompletionCondition, typename ReadHandler>
296 class read_op<AsyncReadStream, boost::array<Elem, 2>,
297 CompletionCondition, ReadHandler>
298 : detail::base_from_completion_cond<CompletionCondition>
299 {
300 public:
301 read_op(AsyncReadStream& stream, const boost::array<Elem, 2>& buffers,
302 CompletionCondition completion_condition, ReadHandler& handler)
303 : detail::base_from_completion_cond<
304 CompletionCondition>(completion_condition),
305 stream_(stream),
306 buffers_(buffers),
307 start_(0),
308 total_transferred_(0),
309 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
310 {
311 }
312
313#if defined(BOOST_ASIO_HAS_MOVE)
314 read_op(const read_op& other)
315 : detail::base_from_completion_cond<CompletionCondition>(other),
316 stream_(other.stream_),
317 buffers_(other.buffers_),
318 start_(other.start_),
319 total_transferred_(other.total_transferred_),
320 handler_(other.handler_)
321 {
322 }
323
324 read_op(read_op&& other)
325 : detail::base_from_completion_cond<CompletionCondition>(other),
326 stream_(other.stream_),
327 buffers_(other.buffers_),
328 start_(other.start_),
329 total_transferred_(other.total_transferred_),
330 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
331 {
332 }
333#endif // defined(BOOST_ASIO_HAS_MOVE)
334
335 void operator()(const boost::system::error_code& ec,
336 std::size_t bytes_transferred, int start = 0)
337 {
338 typename boost::asio::detail::dependent_type<Elem,
339 boost::array<boost::asio::mutable_buffer, 2> >::type bufs = {{
340 boost::asio::mutable_buffer(buffers_[0]),
341 boost::asio::mutable_buffer(buffers_[1]) }};
342 std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
343 std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
344 std::size_t n = 0;
345 switch (start_ = start)
346 {
347 case 1:
348 n = this->check_for_completion(ec, total_transferred_);
349 for (;;)
350 {
351 bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n);
352 bufs[1] = boost::asio::buffer(
353 bufs[1] + (total_transferred_ < buffer_size0
354 ? 0 : total_transferred_ - buffer_size0),
355 n - boost::asio::buffer_size(bufs[0]));
356 stream_.async_read_some(bufs, BOOST_ASIO_MOVE_CAST(read_op)(*this));
357 return; default:
358 total_transferred_ += bytes_transferred;
359 if ((!ec && bytes_transferred == 0)
360 || (n = this->check_for_completion(ec, total_transferred_)) == 0
361 || total_transferred_ == buffer_size0 + buffer_size1)
362 break;
363 }
364
365 handler_(ec, static_cast<const std::size_t&>(total_transferred_));
366 }
367 }
368
369 //private:
370 AsyncReadStream& stream_;
371 boost::array<Elem, 2> buffers_;
372 int start_;
373 std::size_t total_transferred_;
374 ReadHandler handler_;
375 };
376
377#if defined(BOOST_ASIO_HAS_STD_ARRAY)
378
379 template <typename AsyncReadStream, typename Elem,
380 typename CompletionCondition, typename ReadHandler>
381 class read_op<AsyncReadStream, std::array<Elem, 2>,
382 CompletionCondition, ReadHandler>
383 : detail::base_from_completion_cond<CompletionCondition>
384 {
385 public:
386 read_op(AsyncReadStream& stream, const std::array<Elem, 2>& buffers,
387 CompletionCondition completion_condition, ReadHandler& handler)
388 : detail::base_from_completion_cond<
389 CompletionCondition>(completion_condition),
390 stream_(stream),
391 buffers_(buffers),
392 start_(0),
393 total_transferred_(0),
394 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
395 {
396 }
397
398#if defined(BOOST_ASIO_HAS_MOVE)
399 read_op(const read_op& other)
400 : detail::base_from_completion_cond<CompletionCondition>(other),
401 stream_(other.stream_),
402 buffers_(other.buffers_),
403 start_(other.start_),
404 total_transferred_(other.total_transferred_),
405 handler_(other.handler_)
406 {
407 }
408
409 read_op(read_op&& other)
410 : detail::base_from_completion_cond<CompletionCondition>(other),
411 stream_(other.stream_),
412 buffers_(other.buffers_),
413 start_(other.start_),
414 total_transferred_(other.total_transferred_),
415 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
416 {
417 }
418#endif // defined(BOOST_ASIO_HAS_MOVE)
419
420 void operator()(const boost::system::error_code& ec,
421 std::size_t bytes_transferred, int start = 0)
422 {
423 typename boost::asio::detail::dependent_type<Elem,
424 std::array<boost::asio::mutable_buffer, 2> >::type bufs = {{
425 boost::asio::mutable_buffer(buffers_[0]),
426 boost::asio::mutable_buffer(buffers_[1]) }};
427 std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
428 std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
429 std::size_t n = 0;
430 switch (start_ = start)
431 {
432 case 1:
433 n = this->check_for_completion(ec, total_transferred_);
434 for (;;)
435 {
436 bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n);
437 bufs[1] = boost::asio::buffer(
438 bufs[1] + (total_transferred_ < buffer_size0
439 ? 0 : total_transferred_ - buffer_size0),
440 n - boost::asio::buffer_size(bufs[0]));
441 stream_.async_read_some(bufs, BOOST_ASIO_MOVE_CAST(read_op)(*this));
442 return; default:
443 total_transferred_ += bytes_transferred;
444 if ((!ec && bytes_transferred == 0)
445 || (n = this->check_for_completion(ec, total_transferred_)) == 0
446 || total_transferred_ == buffer_size0 + buffer_size1)
447 break;
448 }
449
450 handler_(ec, static_cast<const std::size_t&>(total_transferred_));
451 }
452 }
453
454 //private:
455 AsyncReadStream& stream_;
456 std::array<Elem, 2> buffers_;
457 int start_;
458 std::size_t total_transferred_;
459 ReadHandler handler_;
460 };
461
462#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
463
464 template <typename AsyncReadStream, typename MutableBufferSequence,
465 typename CompletionCondition, typename ReadHandler>
466 inline void* asio_handler_allocate(std::size_t size,
467 read_op<AsyncReadStream, MutableBufferSequence,
468 CompletionCondition, ReadHandler>* this_handler)
469 {
470 return boost_asio_handler_alloc_helpers::allocate(
471 size, this_handler->handler_);
472 }
473
474 template <typename AsyncReadStream, typename MutableBufferSequence,
475 typename CompletionCondition, typename ReadHandler>
476 inline void asio_handler_deallocate(void* pointer, std::size_t size,
477 read_op<AsyncReadStream, MutableBufferSequence,
478 CompletionCondition, ReadHandler>* this_handler)
479 {
480 boost_asio_handler_alloc_helpers::deallocate(
481 pointer, size, this_handler->handler_);
482 }
483
484 template <typename AsyncReadStream, typename MutableBufferSequence,
485 typename CompletionCondition, typename ReadHandler>
486 inline bool asio_handler_is_continuation(
487 read_op<AsyncReadStream, MutableBufferSequence,
488 CompletionCondition, ReadHandler>* this_handler)
489 {
490 return this_handler->start_ == 0 ? true
491 : boost_asio_handler_cont_helpers::is_continuation(
492 this_handler->handler_);
493 }
494
495 template <typename Function, typename AsyncReadStream,
496 typename MutableBufferSequence, typename CompletionCondition,
497 typename ReadHandler>
498 inline void asio_handler_invoke(Function& function,
499 read_op<AsyncReadStream, MutableBufferSequence,
500 CompletionCondition, ReadHandler>* this_handler)
501 {
502 boost_asio_handler_invoke_helpers::invoke(
503 function, this_handler->handler_);
504 }
505
506 template <typename Function, typename AsyncReadStream,
507 typename MutableBufferSequence, typename CompletionCondition,
508 typename ReadHandler>
509 inline void asio_handler_invoke(const Function& function,
510 read_op<AsyncReadStream, MutableBufferSequence,
511 CompletionCondition, ReadHandler>* this_handler)
512 {
513 boost_asio_handler_invoke_helpers::invoke(
514 function, this_handler->handler_);
515 }
516} // namespace detail
517
518template <typename AsyncReadStream, typename MutableBufferSequence,
519 typename CompletionCondition, typename ReadHandler>
520inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
521 void (boost::system::error_code, std::size_t))
522async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
523 CompletionCondition completion_condition,
524 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
525{
526 // If you get an error on the following line it means that your handler does
527 // not meet the documented type requirements for a ReadHandler.
528 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
529
530 detail::async_result_init<
531 ReadHandler, void (boost::system::error_code, std::size_t)> init(
532 BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
533
534 detail::read_op<AsyncReadStream, MutableBufferSequence,
535 CompletionCondition, BOOST_ASIO_HANDLER_TYPE(
536 ReadHandler, void (boost::system::error_code, std::size_t))>(
537 s, buffers, completion_condition, init.handler)(
538 boost::system::error_code(), 0, 1);
539
540 return init.result.get();
541}
542
543template <typename AsyncReadStream, typename MutableBufferSequence,
544 typename ReadHandler>
545inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
546 void (boost::system::error_code, std::size_t))
547async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
548 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
549{
550 // If you get an error on the following line it means that your handler does
551 // not meet the documented type requirements for a ReadHandler.
552 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
553
554 detail::async_result_init<
555 ReadHandler, void (boost::system::error_code, std::size_t)> init(
556 BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
557
558 detail::read_op<AsyncReadStream, MutableBufferSequence,
559 detail::transfer_all_t, BOOST_ASIO_HANDLER_TYPE(
560 ReadHandler, void (boost::system::error_code, std::size_t))>(
561 s, buffers, transfer_all(), init.handler)(
562 boost::system::error_code(), 0, 1);
563
564 return init.result.get();
565}
566
567#if !defined(BOOST_ASIO_NO_IOSTREAM)
568
569namespace detail
570{
571 template <typename AsyncReadStream, typename Allocator,
572 typename CompletionCondition, typename ReadHandler>
573 class read_streambuf_op
574 : detail::base_from_completion_cond<CompletionCondition>
575 {
576 public:
577 read_streambuf_op(AsyncReadStream& stream,
578 basic_streambuf<Allocator>& streambuf,
579 CompletionCondition completion_condition, ReadHandler& handler)
580 : detail::base_from_completion_cond<
581 CompletionCondition>(completion_condition),
582 stream_(stream),
583 streambuf_(streambuf),
584 start_(0),
585 total_transferred_(0),
586 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
587 {
588 }
589
590#if defined(BOOST_ASIO_HAS_MOVE)
591 read_streambuf_op(const read_streambuf_op& other)
592 : detail::base_from_completion_cond<CompletionCondition>(other),
593 stream_(other.stream_),
594 streambuf_(other.streambuf_),
595 start_(other.start_),
596 total_transferred_(other.total_transferred_),
597 handler_(other.handler_)
598 {
599 }
600
601 read_streambuf_op(read_streambuf_op&& other)
602 : detail::base_from_completion_cond<CompletionCondition>(other),
603 stream_(other.stream_),
604 streambuf_(other.streambuf_),
605 start_(other.start_),
606 total_transferred_(other.total_transferred_),
607 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
608 {
609 }
610#endif // defined(BOOST_ASIO_HAS_MOVE)
611
612 void operator()(const boost::system::error_code& ec,
613 std::size_t bytes_transferred, int start = 0)
614 {
615 std::size_t max_size, bytes_available;
616 switch (start_ = start)
617 {
618 case 1:
619 max_size = this->check_for_completion(ec, total_transferred_);
620 bytes_available = read_size_helper(streambuf_, max_size);
621 for (;;)
622 {
623 stream_.async_read_some(streambuf_.prepare(bytes_available),
624 BOOST_ASIO_MOVE_CAST(read_streambuf_op)(*this));
625 return; default:
626 total_transferred_ += bytes_transferred;
627 streambuf_.commit(bytes_transferred);
628 max_size = this->check_for_completion(ec, total_transferred_);
629 bytes_available = read_size_helper(streambuf_, max_size);
630 if ((!ec && bytes_transferred == 0) || bytes_available == 0)
631 break;
632 }
633
634 handler_(ec, static_cast<const std::size_t&>(total_transferred_));
635 }
636 }
637
638 //private:
639 AsyncReadStream& stream_;
640 boost::asio::basic_streambuf<Allocator>& streambuf_;
641 int start_;
642 std::size_t total_transferred_;
643 ReadHandler handler_;
644 };
645
646 template <typename AsyncReadStream, typename Allocator,
647 typename CompletionCondition, typename ReadHandler>
648 inline void* asio_handler_allocate(std::size_t size,
649 read_streambuf_op<AsyncReadStream, Allocator,
650 CompletionCondition, ReadHandler>* this_handler)
651 {
652 return boost_asio_handler_alloc_helpers::allocate(
653 size, this_handler->handler_);
654 }
655
656 template <typename AsyncReadStream, typename Allocator,
657 typename CompletionCondition, typename ReadHandler>
658 inline void asio_handler_deallocate(void* pointer, std::size_t size,
659 read_streambuf_op<AsyncReadStream, Allocator,
660 CompletionCondition, ReadHandler>* this_handler)
661 {
662 boost_asio_handler_alloc_helpers::deallocate(
663 pointer, size, this_handler->handler_);
664 }
665
666 template <typename AsyncReadStream, typename Allocator,
667 typename CompletionCondition, typename ReadHandler>
668 inline bool asio_handler_is_continuation(
669 read_streambuf_op<AsyncReadStream, Allocator,
670 CompletionCondition, ReadHandler>* this_handler)
671 {
672 return this_handler->start_ == 0 ? true
673 : boost_asio_handler_cont_helpers::is_continuation(
674 this_handler->handler_);
675 }
676
677 template <typename Function, typename AsyncReadStream,
678 typename Allocator, typename CompletionCondition, typename ReadHandler>
679 inline void asio_handler_invoke(Function& function,
680 read_streambuf_op<AsyncReadStream, Allocator,
681 CompletionCondition, ReadHandler>* this_handler)
682 {
683 boost_asio_handler_invoke_helpers::invoke(
684 function, this_handler->handler_);
685 }
686
687 template <typename Function, typename AsyncReadStream,
688 typename Allocator, typename CompletionCondition, typename ReadHandler>
689 inline void asio_handler_invoke(const Function& function,
690 read_streambuf_op<AsyncReadStream, Allocator,
691 CompletionCondition, ReadHandler>* this_handler)
692 {
693 boost_asio_handler_invoke_helpers::invoke(
694 function, this_handler->handler_);
695 }
696} // namespace detail
697
698template <typename AsyncReadStream, typename Allocator,
699 typename CompletionCondition, typename ReadHandler>
700inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
701 void (boost::system::error_code, std::size_t))
702async_read(AsyncReadStream& s,
703 boost::asio::basic_streambuf<Allocator>& b,
704 CompletionCondition completion_condition,
705 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
706{
707 // If you get an error on the following line it means that your handler does
708 // not meet the documented type requirements for a ReadHandler.
709 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
710
711 detail::async_result_init<
712 ReadHandler, void (boost::system::error_code, std::size_t)> init(
713 BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
714
715 detail::read_streambuf_op<AsyncReadStream, Allocator,
716 CompletionCondition, BOOST_ASIO_HANDLER_TYPE(
717 ReadHandler, void (boost::system::error_code, std::size_t))>(
718 s, b, completion_condition, init.handler)(
719 boost::system::error_code(), 0, 1);
720
721 return init.result.get();
722}
723
724template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
725inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
726 void (boost::system::error_code, std::size_t))
727async_read(AsyncReadStream& s,
728 boost::asio::basic_streambuf<Allocator>& b,
729 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
730{
731 // If you get an error on the following line it means that your handler does
732 // not meet the documented type requirements for a ReadHandler.
733 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
734
735 detail::async_result_init<
736 ReadHandler, void (boost::system::error_code, std::size_t)> init(
737 BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
738
739 detail::read_streambuf_op<AsyncReadStream, Allocator,
740 detail::transfer_all_t, BOOST_ASIO_HANDLER_TYPE(
741 ReadHandler, void (boost::system::error_code, std::size_t))>(
742 s, b, transfer_all(), init.handler)(
743 boost::system::error_code(), 0, 1);
744
745 return init.result.get();
746}
747
748#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
749
750} // namespace asio
751} // namespace boost
752
753#include <boost/asio/detail/pop_options.hpp>
754
755#endif // BOOST_ASIO_IMPL_READ_HPP
756