std::size_t read_some(const MutableBufferSequence& buffers,
      boost::system::error_code& ec)
  {
    if (!file_)
    {
      ec = boost::asio::error::eof;
      return 0;
    }

    typename MutableBufferSequence::const_iterator iter = buffers.begin();
    typename MutableBufferSequence::const_iterator end = buffers.end();
    for (; iter != end; ++iter)
    {
      boost::asio::mutable_buffer buffer(*iter);
      size_t length = boost::asio::buffer_size(buffer);
      if (length > 0)
      {
        file_.read(boost::asio::buffer_cast<char*>(buffer), length);
        length = file_.gcount();
        if (length == 0 && !file_)
          ec = boost::asio::error::eof;
        return length;
      }
    }

    ec = boost::system::error_code();
    return 0;
  }
Example #2
0
 buffers_adapter(Deduced&& other,
     std::size_t nbegin, std::size_t nout,
         std::size_t nend)
     : bs_(std::forward<Deduced>(other).bs_)
     , begin_(std::next(bs_.begin(), nbegin))
     , out_(std::next(bs_.begin(), nout))
     , end_(std::next(bs_.begin(), nend))
     , max_size_(other.max_size_)
     , in_pos_(other.in_pos_)
     , in_size_(other.in_size_)
     , out_pos_(other.out_pos_)
     , out_end_(other.out_end_)
 {
 }
Example #3
0
 std::size_t read_some(const MutableBufferSequence& buffers
                      , boost::system::error_code& ec)
 {
   ec = boost::system::error_code();
   typename MutableBufferSequence::const_iterator iter = buffers.begin();
   typename MutableBufferSequence::const_iterator end = buffers.end();
   DWORD i = 0;
   size_t buffer_size = 0;
   size_t bytes_transferred = 0;
   size_t total_bytes_transferred = 0;
   for (; !ec && iter != end && i < max_buffers; ++iter, ++i)
   {
     boost::asio::mutable_buffer buffer(*iter);
     buffer_size = boost::asio::buffer_size(buffer);
     bytes_transferred = read_some(
       boost::asio::buffer_cast<char*>(buffer), buffer_size , ec);
     if (bytes_transferred < buffer_size)
       return bytes_transferred;
     total_bytes_transferred += buffer_size;
   }
   return total_bytes_transferred;
 }
  void async_read_some_at(implementation_type& impl, boost::uint64_t offset,
      const MutableBufferSequence& buffers, Handler handler)
  {
    if (!is_open(impl))
    {
      this->get_io_service().post(bind_handler(handler,
            boost::asio::error::bad_descriptor, 0));
      return;
    }

    // Update the ID of the thread from which cancellation is safe.
    if (impl.safe_cancellation_thread_id_ == 0)
      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
      impl.safe_cancellation_thread_id_ = ~DWORD(0);

    // Allocate and construct an operation to wrap the handler.
    typedef read_operation<MutableBufferSequence, Handler> value_type;
    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
    raw_handler_ptr<alloc_traits> raw_ptr(handler);
    handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_, buffers, handler);

    // Find first buffer of non-zero length.
    boost::asio::mutable_buffer buffer;
    typename MutableBufferSequence::const_iterator iter = buffers.begin();
    typename MutableBufferSequence::const_iterator end = buffers.end();
    for (DWORD i = 0; iter != end; ++iter, ++i)
    {
      buffer = boost::asio::mutable_buffer(*iter);
      if (boost::asio::buffer_size(buffer) != 0)
        break;
    }

    // A request to receive 0 bytes on a stream handle is a no-op.
    if (boost::asio::buffer_size(buffer) == 0)
    {
      boost::asio::io_service::work work(this->get_io_service());
      ptr.reset();
      boost::system::error_code error;
      iocp_service_.post(bind_handler(handler, error, 0));
      return;
    }

    // Read some data.
    DWORD bytes_transferred = 0;
    ptr.get()->Offset = offset & 0xFFFFFFFF;
    ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
    BOOL ok = ::ReadFile(impl.handle_,
        boost::asio::buffer_cast<LPVOID>(buffer),
        static_cast<DWORD>(boost::asio::buffer_size(buffer)),
        &bytes_transferred, ptr.get());
    DWORD last_error = ::GetLastError();
    if (!ok && last_error != ERROR_IO_PENDING && last_error != ERROR_MORE_DATA)
    {
      boost::asio::io_service::work work(this->get_io_service());
      ptr.reset();
      boost::system::error_code ec(last_error,
          boost::asio::error::get_system_category());
      iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
    }
    else
    {
      ptr.release();
    }
  }
  size_t read_some_at(implementation_type& impl, boost::uint64_t offset,
      const MutableBufferSequence& buffers, boost::system::error_code& ec)
  {
    if (!is_open(impl))
    {
      ec = boost::asio::error::bad_descriptor;
      return 0;
    }
    
    // Find first buffer of non-zero length.
    boost::asio::mutable_buffer buffer;
    typename MutableBufferSequence::const_iterator iter = buffers.begin();
    typename MutableBufferSequence::const_iterator end = buffers.end();
    for (DWORD i = 0; iter != end; ++iter, ++i)
    {
      buffer = boost::asio::mutable_buffer(*iter);
      if (boost::asio::buffer_size(buffer) != 0)
        break;
    }

    // A request to read 0 bytes on a stream handle is a no-op.
    if (boost::asio::buffer_size(buffer) == 0)
    {
      ec = boost::system::error_code();
      return 0;
    }

    overlapped_wrapper overlapped(ec);
    if (ec)
    {
      return 0;
    }

    // Read some data.
    overlapped.Offset = offset & 0xFFFFFFFF;
    overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
    BOOL ok = ::ReadFile(impl.handle_,
        boost::asio::buffer_cast<LPVOID>(buffer),
        static_cast<DWORD>(boost::asio::buffer_size(buffer)), 0, &overlapped);
    if (!ok) 
    {
      DWORD last_error = ::GetLastError();
      if (last_error != ERROR_IO_PENDING && last_error != ERROR_MORE_DATA)
      {
        if (last_error == ERROR_HANDLE_EOF)
        {
          ec = boost::asio::error::eof;
        }
        else
        {
          ec = boost::system::error_code(last_error,
              boost::asio::error::get_system_category());
        }
        return 0;
      }
    }

    // Wait for the operation to complete.
    DWORD bytes_transferred = 0;
    ok = ::GetOverlappedResult(impl.handle_,
        &overlapped, &bytes_transferred, TRUE);
    if (!ok)
    {
      DWORD last_error = ::GetLastError();
      if (last_error == ERROR_HANDLE_EOF)
      {
        ec = boost::asio::error::eof;
      }
      else
      {
        ec = boost::system::error_code(last_error,
            boost::asio::error::get_system_category());
      }
    }

    ec = boost::system::error_code();
    return bytes_transferred;
  }