10ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
20ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// impl/read.hpp
30ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// ~~~~~~~~~~~~~
40ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
50ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
60ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
70ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// Distributed under the Boost Software License, Version 1.0. (See accompanying
80ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
90ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#ifndef ASIO_IMPL_READ_HPP
120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#define ASIO_IMPL_READ_HPP
130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include <algorithm>
160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/buffer.hpp"
170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/completion_condition.hpp"
180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/array_fwd.hpp"
190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/base_from_completion_cond.hpp"
200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/bind_handler.hpp"
210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/consuming_buffers.hpp"
220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/dependent_type.hpp"
230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/handler_alloc_helpers.hpp"
240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/handler_cont_helpers.hpp"
250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/handler_invoke_helpers.hpp"
260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/handler_type_requirements.hpp"
270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/throw_error.hpp"
280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/error.hpp"
290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/push_options.hpp"
310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffienamespace asio {
330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffietemplate <typename SyncReadStream, typename MutableBufferSequence,
350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    typename CompletionCondition>
360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffiestd::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    CompletionCondition completion_condition, asio::error_code& ec)
380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  ec = asio::error_code();
400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::detail::consuming_buffers<
410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    mutable_buffer, MutableBufferSequence> tmp(buffers);
420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  std::size_t total_transferred = 0;
430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  tmp.prepare(detail::adapt_completion_condition_result(
440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        completion_condition(ec, total_transferred)));
450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  while (tmp.begin() != tmp.end())
460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    std::size_t bytes_transferred = s.read_some(tmp, ec);
480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    tmp.consume(bytes_transferred);
490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    total_transferred += bytes_transferred;
500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    tmp.prepare(detail::adapt_completion_condition_result(
510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          completion_condition(ec, total_transferred)));
520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  return total_transferred;
540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffietemplate <typename SyncReadStream, typename MutableBufferSequence>
570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieinline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers)
580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::error_code ec;
600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::detail::throw_error(ec, "read");
620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  return bytes_transferred;
630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffietemplate <typename SyncReadStream, typename MutableBufferSequence>
660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieinline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code& ec)
680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  return read(s, buffers, transfer_all(), ec);
700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffietemplate <typename SyncReadStream, typename MutableBufferSequence,
730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    typename CompletionCondition>
740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieinline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    CompletionCondition completion_condition)
760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::error_code ec;
780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  std::size_t bytes_transferred = read(s, buffers, completion_condition, ec);
790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::detail::throw_error(ec, "read");
800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  return bytes_transferred;
810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffienamespace detail
850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename AsyncReadStream, typename MutableBufferSequence,
870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename CompletionCondition, typename ReadHandler>
880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  class read_op
890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : detail::base_from_completion_cond<CompletionCondition>
900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  public:
920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers,
930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        CompletionCondition completion_condition, ReadHandler& handler)
940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<
950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          CompletionCondition>(completion_condition),
960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(stream),
970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_(buffers),
980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(0),
990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(0),
1000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
1010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
1020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
1030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    read_op(const read_op& other)
1050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<CompletionCondition>(other),
1060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(other.stream_),
1070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_(other.buffers_),
1080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(other.start_),
1090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(other.total_transferred_),
1100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(other.handler_)
1110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
1120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
1130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    read_op(read_op&& other)
1150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<CompletionCondition>(other),
1160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(other.stream_),
1170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_(other.buffers_),
1180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(other.start_),
1190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(other.total_transferred_),
1200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
1210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
1220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
1230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    void operator()(const asio::error_code& ec,
1250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        std::size_t bytes_transferred, int start = 0)
1260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
1270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      switch (start_ = start)
1280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      {
1290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        case 1:
1300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_.prepare(this->check_for_completion(ec, total_transferred_));
1310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        for (;;)
1320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        {
1330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          stream_.async_read_some(buffers_,
1340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              ASIO_MOVE_CAST(read_op)(*this));
1350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          return; default:
1360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          total_transferred_ += bytes_transferred;
1370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          buffers_.consume(bytes_transferred);
1380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          buffers_.prepare(this->check_for_completion(ec, total_transferred_));
1390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          if ((!ec && bytes_transferred == 0)
1400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              || buffers_.begin() == buffers_.end())
1410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie            break;
1420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        }
1430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
1450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      }
1460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
1470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  //private:
1490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    AsyncReadStream& stream_;
1500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::consuming_buffers<
1510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      mutable_buffer, MutableBufferSequence> buffers_;
1520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    int start_;
1530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    std::size_t total_transferred_;
1540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    ReadHandler handler_;
1550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  };
1560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename AsyncReadStream,
1580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename CompletionCondition, typename ReadHandler>
1590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  class read_op<AsyncReadStream, asio::mutable_buffers_1,
1600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      CompletionCondition, ReadHandler>
1610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : detail::base_from_completion_cond<CompletionCondition>
1620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  public:
1640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    read_op(AsyncReadStream& stream,
1650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        const asio::mutable_buffers_1& buffers,
1660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        CompletionCondition completion_condition, ReadHandler& handler)
1670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<
1680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          CompletionCondition>(completion_condition),
1690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(stream),
1700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffer_(buffers),
1710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(0),
1720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(0),
1730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
1740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
1750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
1760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    read_op(const read_op& other)
1780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<CompletionCondition>(other),
1790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(other.stream_),
1800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffer_(other.buffer_),
1810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(other.start_),
1820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(other.total_transferred_),
1830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(other.handler_)
1840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
1850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
1860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    read_op(read_op&& other)
1880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<CompletionCondition>(other),
1890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(other.stream_),
1900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffer_(other.buffer_),
1910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(other.start_),
1920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(other.total_transferred_),
1930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
1940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
1950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
1960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    void operator()(const asio::error_code& ec,
1980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        std::size_t bytes_transferred, int start = 0)
1990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
2000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      std::size_t n = 0;
2010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      switch (start_ = start)
2020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      {
2030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        case 1:
2040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        n = this->check_for_completion(ec, total_transferred_);
2050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        for (;;)
2060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        {
2070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          stream_.async_read_some(
2080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              asio::buffer(buffer_ + total_transferred_, n),
2090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              ASIO_MOVE_CAST(read_op)(*this));
2100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          return; default:
2110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          total_transferred_ += bytes_transferred;
2120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          if ((!ec && bytes_transferred == 0)
2130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              || (n = this->check_for_completion(ec, total_transferred_)) == 0
2140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              || total_transferred_ == asio::buffer_size(buffer_))
2150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie            break;
2160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        }
2170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
2190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      }
2200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
2210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  //private:
2230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    AsyncReadStream& stream_;
2240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::mutable_buffer buffer_;
2250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    int start_;
2260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    std::size_t total_transferred_;
2270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    ReadHandler handler_;
2280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  };
2290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename AsyncReadStream, typename Elem,
2310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename CompletionCondition, typename ReadHandler>
2320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  class read_op<AsyncReadStream, boost::array<Elem, 2>,
2330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      CompletionCondition, ReadHandler>
2340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : detail::base_from_completion_cond<CompletionCondition>
2350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
2360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  public:
2370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    read_op(AsyncReadStream& stream, const boost::array<Elem, 2>& buffers,
2380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        CompletionCondition completion_condition, ReadHandler& handler)
2390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<
2400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          CompletionCondition>(completion_condition),
2410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(stream),
2420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_(buffers),
2430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(0),
2440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(0),
2450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
2460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
2470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
2480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    read_op(const read_op& other)
2500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<CompletionCondition>(other),
2510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(other.stream_),
2520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_(other.buffers_),
2530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(other.start_),
2540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(other.total_transferred_),
2550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(other.handler_)
2560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
2570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
2580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    read_op(read_op&& other)
2600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<CompletionCondition>(other),
2610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(other.stream_),
2620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_(other.buffers_),
2630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(other.start_),
2640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(other.total_transferred_),
2650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
2660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
2670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
2680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    void operator()(const asio::error_code& ec,
2700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        std::size_t bytes_transferred, int start = 0)
2710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
2720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename asio::detail::dependent_type<Elem,
2730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          boost::array<asio::mutable_buffer, 2> >::type bufs = {{
2740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        asio::mutable_buffer(buffers_[0]),
2750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        asio::mutable_buffer(buffers_[1]) }};
2760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      std::size_t buffer_size0 = asio::buffer_size(bufs[0]);
2770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      std::size_t buffer_size1 = asio::buffer_size(bufs[1]);
2780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      std::size_t n = 0;
2790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      switch (start_ = start)
2800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      {
2810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        case 1:
2820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        n = this->check_for_completion(ec, total_transferred_);
2830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        for (;;)
2840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        {
2850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          bufs[0] = asio::buffer(bufs[0] + total_transferred_, n);
2860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          bufs[1] = asio::buffer(
2870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              bufs[1] + (total_transferred_ < buffer_size0
2880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie                ? 0 : total_transferred_ - buffer_size0),
2890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              n - asio::buffer_size(bufs[0]));
2900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          stream_.async_read_some(bufs, ASIO_MOVE_CAST(read_op)(*this));
2910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          return; default:
2920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          total_transferred_ += bytes_transferred;
2930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          if ((!ec && bytes_transferred == 0)
2940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              || (n = this->check_for_completion(ec, total_transferred_)) == 0
2950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              || total_transferred_ == buffer_size0 + buffer_size1)
2960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie            break;
2970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        }
2980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
3000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      }
3010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
3020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  //private:
3040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    AsyncReadStream& stream_;
3050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    boost::array<Elem, 2> buffers_;
3060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    int start_;
3070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    std::size_t total_transferred_;
3080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    ReadHandler handler_;
3090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  };
3100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename AsyncReadStream, typename Elem,
3130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename CompletionCondition, typename ReadHandler>
3140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  class read_op<AsyncReadStream, std::array<Elem, 2>,
3150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      CompletionCondition, ReadHandler>
3160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : detail::base_from_completion_cond<CompletionCondition>
3170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
3180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  public:
3190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    read_op(AsyncReadStream& stream, const std::array<Elem, 2>& buffers,
3200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        CompletionCondition completion_condition, ReadHandler& handler)
3210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<
3220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          CompletionCondition>(completion_condition),
3230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(stream),
3240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_(buffers),
3250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(0),
3260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(0),
3270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
3280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
3290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
3300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    read_op(const read_op& other)
3320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<CompletionCondition>(other),
3330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(other.stream_),
3340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_(other.buffers_),
3350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(other.start_),
3360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(other.total_transferred_),
3370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(other.handler_)
3380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
3390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
3400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    read_op(read_op&& other)
3420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<CompletionCondition>(other),
3430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(other.stream_),
3440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_(other.buffers_),
3450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(other.start_),
3460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(other.total_transferred_),
3470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
3480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
3490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
3500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    void operator()(const asio::error_code& ec,
3520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        std::size_t bytes_transferred, int start = 0)
3530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
3540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename asio::detail::dependent_type<Elem,
3550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          std::array<asio::mutable_buffer, 2> >::type bufs = {{
3560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        asio::mutable_buffer(buffers_[0]),
3570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        asio::mutable_buffer(buffers_[1]) }};
3580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      std::size_t buffer_size0 = asio::buffer_size(bufs[0]);
3590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      std::size_t buffer_size1 = asio::buffer_size(bufs[1]);
3600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      std::size_t n = 0;
3610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      switch (start_ = start)
3620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      {
3630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        case 1:
3640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        n = this->check_for_completion(ec, total_transferred_);
3650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        for (;;)
3660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        {
3670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          bufs[0] = asio::buffer(bufs[0] + total_transferred_, n);
3680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          bufs[1] = asio::buffer(
3690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              bufs[1] + (total_transferred_ < buffer_size0
3700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie                ? 0 : total_transferred_ - buffer_size0),
3710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              n - asio::buffer_size(bufs[0]));
3720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          stream_.async_read_some(bufs, ASIO_MOVE_CAST(read_op)(*this));
3730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          return; default:
3740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          total_transferred_ += bytes_transferred;
3750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          if ((!ec && bytes_transferred == 0)
3760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              || (n = this->check_for_completion(ec, total_transferred_)) == 0
3770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              || total_transferred_ == buffer_size0 + buffer_size1)
3780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie            break;
3790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        }
3800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
3820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      }
3830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
3840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  //private:
3860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    AsyncReadStream& stream_;
3870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    std::array<Elem, 2> buffers_;
3880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    int start_;
3890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    std::size_t total_transferred_;
3900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    ReadHandler handler_;
3910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  };
3920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename AsyncReadStream, typename MutableBufferSequence,
3950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename CompletionCondition, typename ReadHandler>
3960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  inline void* asio_handler_allocate(std::size_t size,
3970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      read_op<AsyncReadStream, MutableBufferSequence,
3980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        CompletionCondition, ReadHandler>* this_handler)
3990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
4000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return asio_handler_alloc_helpers::allocate(
4010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        size, this_handler->handler_);
4020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
4030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename AsyncReadStream, typename MutableBufferSequence,
4050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename CompletionCondition, typename ReadHandler>
4060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  inline void asio_handler_deallocate(void* pointer, std::size_t size,
4070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      read_op<AsyncReadStream, MutableBufferSequence,
4080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        CompletionCondition, ReadHandler>* this_handler)
4090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
4100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio_handler_alloc_helpers::deallocate(
4110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        pointer, size, this_handler->handler_);
4120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
4130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename AsyncReadStream, typename MutableBufferSequence,
4150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename CompletionCondition, typename ReadHandler>
4160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  inline bool asio_handler_is_continuation(
4170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      read_op<AsyncReadStream, MutableBufferSequence,
4180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        CompletionCondition, ReadHandler>* this_handler)
4190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
4200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this_handler->start_ == 0 ? true
4210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : asio_handler_cont_helpers::is_continuation(
4220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          this_handler->handler_);
4230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
4240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename Function, typename AsyncReadStream,
4260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename MutableBufferSequence, typename CompletionCondition,
4270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename ReadHandler>
4280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  inline void asio_handler_invoke(Function& function,
4290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      read_op<AsyncReadStream, MutableBufferSequence,
4300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        CompletionCondition, ReadHandler>* this_handler)
4310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
4320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio_handler_invoke_helpers::invoke(
4330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        function, this_handler->handler_);
4340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
4350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename Function, typename AsyncReadStream,
4370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename MutableBufferSequence, typename CompletionCondition,
4380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename ReadHandler>
4390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  inline void asio_handler_invoke(const Function& function,
4400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      read_op<AsyncReadStream, MutableBufferSequence,
4410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        CompletionCondition, ReadHandler>* this_handler)
4420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
4430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio_handler_invoke_helpers::invoke(
4440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        function, this_handler->handler_);
4450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
4460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie} // namespace detail
4470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffietemplate <typename AsyncReadStream, typename MutableBufferSequence,
4490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    typename CompletionCondition, typename ReadHandler>
4500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieinline ASIO_INITFN_RESULT_TYPE(ReadHandler,
4510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    void (asio::error_code, std::size_t))
4520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieasync_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
4530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    CompletionCondition completion_condition,
4540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    ASIO_MOVE_ARG(ReadHandler) handler)
4550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
4560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  // If you get an error on the following line it means that your handler does
4570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  // not meet the documented type requirements for a ReadHandler.
4580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
4590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  detail::async_result_init<
4610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    ReadHandler, void (asio::error_code, std::size_t)> init(
4620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      ASIO_MOVE_CAST(ReadHandler)(handler));
4630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  detail::read_op<AsyncReadStream, MutableBufferSequence,
4650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    CompletionCondition, ASIO_HANDLER_TYPE(
4660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      ReadHandler, void (asio::error_code, std::size_t))>(
4670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        s, buffers, completion_condition, init.handler)(
4680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          asio::error_code(), 0, 1);
4690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  return init.result.get();
4710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
4720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffietemplate <typename AsyncReadStream, typename MutableBufferSequence,
4740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    typename ReadHandler>
4750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieinline ASIO_INITFN_RESULT_TYPE(ReadHandler,
4760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    void (asio::error_code, std::size_t))
4770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieasync_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
4780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    ASIO_MOVE_ARG(ReadHandler) handler)
4790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
4800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  // If you get an error on the following line it means that your handler does
4810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  // not meet the documented type requirements for a ReadHandler.
4820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
4830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  detail::async_result_init<
4850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    ReadHandler, void (asio::error_code, std::size_t)> init(
4860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      ASIO_MOVE_CAST(ReadHandler)(handler));
4870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  detail::read_op<AsyncReadStream, MutableBufferSequence,
4890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    detail::transfer_all_t, ASIO_HANDLER_TYPE(
4900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      ReadHandler, void (asio::error_code, std::size_t))>(
4910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        s, buffers, transfer_all(), init.handler)(
4920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          asio::error_code(), 0, 1);
4930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  return init.result.get();
4950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
4960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie} // namespace asio
4990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/pop_options.hpp"
5010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#endif // ASIO_IMPL_READ_HPP
503