Move read/async_read/write/async_write functions for basic_streambuf into

the read.hpp and write.hpp header files.
This commit is contained in:
chris_kohlhoff 2006-06-18 02:12:54 +00:00
parent f50c88ccac
commit c115a2da9b
6 changed files with 842 additions and 204 deletions

View File

@ -26,9 +26,6 @@
#include <vector>
#include "asio/detail/pop_options.hpp"
#include "asio/completion_condition.hpp"
#include "asio/error_handler.hpp"
#include "asio/write.hpp"
#include "asio/detail/noncopyable.hpp"
namespace asio {
@ -189,214 +186,197 @@ private:
std::vector<char_type, Allocator> buffer_;
};
template <typename Sync_Read_Stream, typename Allocator,
typename Completion_Condition, typename Error_Handler>
std::size_t read(Sync_Read_Stream& s,
asio::basic_streambuf<Allocator>& b,
Completion_Condition completion_condition, Error_Handler error_handler)
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_STREAMBUF_HPP
// basic_streambuf.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_STREAMBUF_HPP
#define ASIO_BASIC_STREAMBUF_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <algorithm>
#include <limits>
#include <memory>
#include <stdexcept>
#include <streambuf>
#include <vector>
#include "asio/detail/pop_options.hpp"
#include "asio/detail/noncopyable.hpp"
namespace asio {
/// Automatically resizable buffer class based on std::streambuf.
template <typename Allocator = std::allocator<char> >
class basic_streambuf
: public std::streambuf,
private noncopyable
{
std::size_t total_transferred = 0;
for (;;)
public:
#if defined(GENERATING_DOCUMENTATION)
/// The type used to represent the get area as a list of buffers.
typedef implementation_defined const_buffers_type;
/// The type used to represent the put area as a list of buffers.
typedef implementation_defined mutable_buffers_type;
#else
typedef asio::const_buffer_container_1 const_buffers_type;
typedef asio::mutable_buffer_container_1 mutable_buffers_type;
#endif
/// Construct a buffer with a specified maximum size.
explicit basic_streambuf(
std::size_t max_size = (std::numeric_limits<std::size_t>::max)(),
const Allocator& allocator = Allocator())
: max_size_(max_size),
buffer_(allocator)
{
typename Sync_Read_Stream::error_type e;
std::size_t bytes_transferred = s.read_some(
b.prepare(512), assign_error(e));
b.commit(bytes_transferred);
total_transferred += bytes_transferred;
if (completion_condition(e, total_transferred))
std::size_t pend = (std::min<std::size_t>)(max_size_, buffer_delta);
buffer_.resize((std::max<std::size_t>)(pend, 1));
setg(&buffer_[0], &buffer_[0], &buffer_[0]);
setp(&buffer_[0], &buffer_[0] + pend);
}
/// Return the size of the get area in characters.
std::size_t size() const
{
return pptr() - gptr();
}
/// Get a list of buffers that represents the get area.
const_buffers_type data() const
{
return asio::buffer(asio::const_buffer(gptr(),
(pptr() - gptr()) * sizeof(char_type)));
}
/// Get a list of buffers that represents the put area, with the given size.
mutable_buffers_type prepare(std::size_t size)
{
reserve(size);
return asio::buffer(asio::mutable_buffer(
pptr(), size * sizeof(char_type)));
}
/// Move the start of the put area by the specified number of characters.
void commit(std::size_t n)
{
if (pptr() + n > epptr())
n = epptr() - pptr();
pbump(n);
}
/// Move the start of the get area by the specified number of characters.
void consume(std::size_t n)
{
while (n > 0)
{
error_handler(e);
return total_transferred;
sbumpc();
--n;
}
}
typename Sync_Read_Stream::error_type e;
error_handler(e);
return total_transferred;
}
template <typename Sync_Read_Stream, typename Allocator>
inline std::size_t read(Sync_Read_Stream& s,
asio::basic_streambuf<Allocator>& b)
{
return read(s, b, transfer_all(), throw_error());
}
protected:
enum { buffer_delta = 128 };
template <typename Sync_Read_Stream, typename Allocator,
typename Completion_Condition>
inline std::size_t read(Sync_Read_Stream& s,
asio::basic_streambuf<Allocator>& b,
Completion_Condition completion_condition)
{
return read(s, b, completion_condition, throw_error());
}
namespace detail
{
template <typename Async_Read_Stream, typename Allocator,
typename Completion_Condition, typename Handler>
class read_streambuf_handler
int_type underflow()
{
public:
read_streambuf_handler(Async_Read_Stream& stream,
basic_streambuf<Allocator>& streambuf,
Completion_Condition completion_condition, Handler handler)
: stream_(stream),
streambuf_(streambuf),
total_transferred_(0),
completion_condition_(completion_condition),
handler_(handler)
if (gptr() < pptr())
{
setg(&buffer_[0], gptr(), pptr());
return traits_type::to_int_type(*gptr());
}
else
{
return traits_type::eof();
}
}
int_type overflow(int_type c)
{
if (!traits_type::eq_int_type(c, traits_type::eof()))
{
if (pptr() == epptr())
{
std::size_t buffer_size = pptr() - gptr();
if (buffer_size < max_size_ && max_size_ - buffer_size < buffer_delta)
{
reserve(max_size_ - buffer_size);
}
else
{
reserve(buffer_delta);
}
}
*pptr() = traits_type::to_char_type(c);
pbump(1);
return c;
}
void operator()(const typename Async_Read_Stream::error_type& e,
std::size_t bytes_transferred)
return traits_type::not_eof(c);
}
void reserve(std::size_t n)
{
// Get current stream positions as offsets.
std::size_t gnext = gptr() - &buffer_[0];
std::size_t gend = egptr() - &buffer_[0];
std::size_t pnext = pptr() - &buffer_[0];
std::size_t pend = epptr() - &buffer_[0];
// Check if there is already enough space in the put area.
if (n <= pend - pnext)
{
total_transferred_ += bytes_transferred;
streambuf_.commit(bytes_transferred);
if (completion_condition_(e, total_transferred_))
return;
}
// Shift existing contents of get area to start of buffer.
if (gnext > 0)
{
std::rotate(&buffer_[0], &buffer_[0] + gnext, &buffer_[0] + pend);
gend -= gnext;
pnext -= gnext;
}
// Ensure buffer is large enough to hold at least the specified size.
if (n > pend - pnext)
{
if (n <= max_size_ & pnext <= max_size_ - n)
{
stream_.io_service().dispatch(
detail::bind_handler(handler_, e, total_transferred_));
buffer_.resize((std::max<std::size_t>)(pnext + n, 1));
}
else
{
stream_.async_read_some(streambuf_.prepare(512), *this);
throw std::length_error("asio::streambuf too long");
}
}
friend void* asio_handler_allocate(std::size_t size,
read_streambuf_handler<Async_Read_Stream, Allocator,
Completion_Condition, Handler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, &this_handler->handler_);
}
// Update stream positions.
setg(&buffer_[0], &buffer_[0], &buffer_[0] + gend);
setp(&buffer_[0] + pnext, &buffer_[0] + pnext + n);
}
friend void asio_handler_deallocate(void* pointer, std::size_t size,
read_streambuf_handler<Async_Read_Stream, Allocator,
Completion_Condition, Handler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, &this_handler->handler_);
}
private:
Async_Read_Stream& stream_;
asio::basic_streambuf<Allocator>& streambuf_;
std::size_t total_transferred_;
Completion_Condition completion_condition_;
Handler handler_;
};
} // namespace detail
template <typename Async_Read_Stream, typename Allocator,
typename Completion_Condition, typename Handler>
inline void async_read(Async_Read_Stream& s,
asio::basic_streambuf<Allocator>& b,
Completion_Condition completion_condition, Handler handler)
{
s.async_read_some(b.prepare(512),
detail::read_streambuf_handler<Async_Read_Stream, Allocator,
Completion_Condition, Handler>(
s, b, completion_condition, handler));
}
template <typename Async_Read_Stream, typename Allocator, typename Handler>
inline void async_read(Async_Read_Stream& s,
asio::basic_streambuf<Allocator>& b, Handler handler)
{
async_read(s, b, transfer_all(), handler);
}
template <typename Sync_Write_Stream, typename Allocator,
typename Completion_Condition, typename Error_Handler>
std::size_t write(Sync_Write_Stream& s,
asio::basic_streambuf<Allocator>& b,
Completion_Condition completion_condition, Error_Handler error_handler)
{
typename Sync_Write_Stream::error_type error;
std::size_t bytes_transferred = write(s, b.data(),
completion_condition, asio::assign_error(error));
b.consume(bytes_transferred);
error_handler(error);
return bytes_transferred;
}
template <typename Sync_Write_Stream, typename Allocator>
inline std::size_t write(Sync_Write_Stream& s,
asio::basic_streambuf<Allocator>& b)
{
return write(s, b, transfer_all(), throw_error());
}
template <typename Sync_Write_Stream, typename Allocator,
typename Completion_Condition>
inline std::size_t write(Sync_Write_Stream& s,
asio::basic_streambuf<Allocator>& b,
Completion_Condition completion_condition)
{
return write(s, b, completion_condition, throw_error());
}
namespace detail
{
template <typename Async_Write_Stream, typename Allocator, typename Handler>
class write_streambuf_handler
{
public:
write_streambuf_handler(asio::basic_streambuf<Allocator>& streambuf,
Handler handler)
: streambuf_(streambuf),
handler_(handler)
{
}
void operator()(const typename Async_Write_Stream::error_type& e,
std::size_t bytes_transferred)
{
streambuf_.consume(bytes_transferred);
handler_(e, bytes_transferred);
}
friend void* asio_handler_allocate(std::size_t size,
write_streambuf_handler<Async_Write_Stream,
Allocator, Handler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, &this_handler->handler_);
}
friend void asio_handler_deallocate(void* pointer, std::size_t size,
write_streambuf_handler<Async_Write_Stream,
Allocator, Handler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, &this_handler->handler_);
}
private:
asio::basic_streambuf<Allocator>& streambuf_;
Handler handler_;
};
} // namespace detail
template <typename Async_Write_Stream, typename Allocator,
typename Completion_Condition, typename Handler>
inline void async_write(Async_Write_Stream& s,
asio::basic_streambuf<Allocator>& b,
Completion_Condition completion_condition, Handler handler)
{
async_write(s, b.data(),
detail::write_streambuf_handler<Async_Write_Stream, Allocator, Handler>(
b, handler));
}
template <typename Async_Write_Stream, typename Allocator, typename Handler>
inline void async_write(Async_Write_Stream& s,
asio::basic_streambuf<Allocator>& b, Handler handler)
{
async_write(s, b, transfer_all(), handler);
}
private:
std::size_t max_size_;
std::vector<char_type, Allocator> buffer_;
};
} // namespace asio

View File

@ -65,6 +65,47 @@ inline std::size_t read(Sync_Read_Stream& s, const Mutable_Buffers& buffers,
return read(s, buffers, completion_condition, throw_error());
}
template <typename Sync_Read_Stream, typename Allocator,
typename Completion_Condition, typename Error_Handler>
std::size_t read(Sync_Read_Stream& s,
asio::basic_streambuf<Allocator>& b,
Completion_Condition completion_condition, Error_Handler error_handler)
{
std::size_t total_transferred = 0;
for (;;)
{
typename Sync_Read_Stream::error_type e;
std::size_t bytes_transferred = s.read_some(
b.prepare(512), assign_error(e));
b.commit(bytes_transferred);
total_transferred += bytes_transferred;
if (completion_condition(e, total_transferred))
{
error_handler(e);
return total_transferred;
}
}
typename Sync_Read_Stream::error_type e;
error_handler(e);
return total_transferred;
}
template <typename Sync_Read_Stream, typename Allocator>
inline std::size_t read(Sync_Read_Stream& s,
asio::basic_streambuf<Allocator>& b)
{
return read(s, b, transfer_all(), throw_error());
}
template <typename Sync_Read_Stream, typename Allocator,
typename Completion_Condition>
inline std::size_t read(Sync_Read_Stream& s,
asio::basic_streambuf<Allocator>& b,
Completion_Condition completion_condition)
{
return read(s, b, completion_condition, throw_error());
}
namespace detail
{
template <typename Async_Read_Stream, typename Mutable_Buffers,
@ -144,6 +185,84 @@ inline void async_read(Async_Read_Stream& s, const Mutable_Buffers& buffers,
async_read(s, buffers, transfer_all(), handler);
}
namespace detail
{
template <typename Async_Read_Stream, typename Allocator,
typename Completion_Condition, typename Handler>
class read_streambuf_handler
{
public:
read_streambuf_handler(Async_Read_Stream& stream,
basic_streambuf<Allocator>& streambuf,
Completion_Condition completion_condition, Handler handler)
: stream_(stream),
streambuf_(streambuf),
total_transferred_(0),
completion_condition_(completion_condition),
handler_(handler)
{
}
void operator()(const typename Async_Read_Stream::error_type& e,
std::size_t bytes_transferred)
{
total_transferred_ += bytes_transferred;
streambuf_.commit(bytes_transferred);
if (completion_condition_(e, total_transferred_))
{
stream_.io_service().dispatch(
detail::bind_handler(handler_, e, total_transferred_));
}
else
{
stream_.async_read_some(streambuf_.prepare(512), *this);
}
}
friend void* asio_handler_allocate(std::size_t size,
read_streambuf_handler<Async_Read_Stream, Allocator,
Completion_Condition, Handler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, &this_handler->handler_);
}
friend void asio_handler_deallocate(void* pointer, std::size_t size,
read_streambuf_handler<Async_Read_Stream, Allocator,
Completion_Condition, Handler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, &this_handler->handler_);
}
private:
Async_Read_Stream& stream_;
asio::basic_streambuf<Allocator>& streambuf_;
std::size_t total_transferred_;
Completion_Condition completion_condition_;
Handler handler_;
};
} // namespace detail
template <typename Async_Read_Stream, typename Allocator,
typename Completion_Condition, typename Handler>
inline void async_read(Async_Read_Stream& s,
asio::basic_streambuf<Allocator>& b,
Completion_Condition completion_condition, Handler handler)
{
s.async_read_some(b.prepare(512),
detail::read_streambuf_handler<Async_Read_Stream, Allocator,
Completion_Condition, Handler>(
s, b, completion_condition, handler));
}
template <typename Async_Read_Stream, typename Allocator, typename Handler>
inline void async_read(Async_Read_Stream& s,
asio::basic_streambuf<Allocator>& b, Handler handler)
{
async_read(s, b, transfer_all(), handler);
}
} // namespace asio
#include "asio/detail/pop_options.hpp"

View File

@ -65,6 +65,36 @@ inline std::size_t write(Sync_Write_Stream& s, const Const_Buffers& buffers,
return write(s, buffers, completion_condition, throw_error());
}
template <typename Sync_Write_Stream, typename Allocator,
typename Completion_Condition, typename Error_Handler>
std::size_t write(Sync_Write_Stream& s,
asio::basic_streambuf<Allocator>& b,
Completion_Condition completion_condition, Error_Handler error_handler)
{
typename Sync_Write_Stream::error_type error;
std::size_t bytes_transferred = write(s, b.data(),
completion_condition, asio::assign_error(error));
b.consume(bytes_transferred);
error_handler(error);
return bytes_transferred;
}
template <typename Sync_Write_Stream, typename Allocator>
inline std::size_t write(Sync_Write_Stream& s,
asio::basic_streambuf<Allocator>& b)
{
return write(s, b, transfer_all(), throw_error());
}
template <typename Sync_Write_Stream, typename Allocator,
typename Completion_Condition>
inline std::size_t write(Sync_Write_Stream& s,
asio::basic_streambuf<Allocator>& b,
Completion_Condition completion_condition)
{
return write(s, b, completion_condition, throw_error());
}
namespace detail
{
template <typename Async_Write_Stream, typename Const_Buffers,
@ -143,6 +173,66 @@ inline void async_write(Async_Write_Stream& s, const Const_Buffers& buffers,
async_write(s, buffers, transfer_all(), handler);
}
namespace detail
{
template <typename Async_Write_Stream, typename Allocator, typename Handler>
class write_streambuf_handler
{
public:
write_streambuf_handler(asio::basic_streambuf<Allocator>& streambuf,
Handler handler)
: streambuf_(streambuf),
handler_(handler)
{
}
void operator()(const typename Async_Write_Stream::error_type& e,
std::size_t bytes_transferred)
{
streambuf_.consume(bytes_transferred);
handler_(e, bytes_transferred);
}
friend void* asio_handler_allocate(std::size_t size,
write_streambuf_handler<Async_Write_Stream,
Allocator, Handler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, &this_handler->handler_);
}
friend void asio_handler_deallocate(void* pointer, std::size_t size,
write_streambuf_handler<Async_Write_Stream,
Allocator, Handler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, &this_handler->handler_);
}
private:
asio::basic_streambuf<Allocator>& streambuf_;
Handler handler_;
};
} // namespace detail
template <typename Async_Write_Stream, typename Allocator,
typename Completion_Condition, typename Handler>
inline void async_write(Async_Write_Stream& s,
asio::basic_streambuf<Allocator>& b,
Completion_Condition completion_condition, Handler handler)
{
async_write(s, b.data(),
detail::write_streambuf_handler<Async_Write_Stream, Allocator, Handler>(
b, handler));
}
template <typename Async_Write_Stream, typename Allocator, typename Handler>
inline void async_write(Async_Write_Stream& s,
asio::basic_streambuf<Allocator>& b, Handler handler)
{
async_write(s, b, transfer_all(), handler);
}
} // namespace asio
#include "asio/detail/pop_options.hpp"

View File

@ -22,6 +22,8 @@
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/basic_streambuf.hpp"
namespace asio {
/**
@ -175,6 +177,122 @@ template <typename Sync_Read_Stream, typename Mutable_Buffers,
std::size_t read(Sync_Read_Stream& s, const Mutable_Buffers& buffers,
Completion_Condition completion_condition, Error_Handler error_handler);
/// Attempt to read a certain amount of data from a stream before returning.
/**
* This function is used to read a certain number of bytes of data from a
* stream. The call will block until one of the following conditions is true:
*
* @li An error occurred.
*
* This operation is implemented in terms of one or more calls to the stream's
* read_some function.
*
* @param s The stream from which the data is to be read. The type must support
* the Sync_Read_Stream concept.
*
* @param b The basic_streambuf object into which the data will be read.
*
* @returns The number of bytes transferred.
*
* @throws Sync_Read_Stream::error_type Thrown on failure.
*
* @note This overload is equivalent to calling:
* @code asio::read(
* s, b,
* asio::transfer_all(),
* asio::throw_error()); @endcode
*/
template <typename Sync_Read_Stream, typename Allocator>
std::size_t read(Sync_Read_Stream& s, basic_streambuf<Allocator>& b);
/// Attempt to read a certain amount of data from a stream before returning.
/**
* This function is used to read a certain number of bytes of data from a
* stream. The call will block until one of the following conditions is true:
*
* @li The completion_condition function object returns true.
*
* This operation is implemented in terms of one or more calls to the stream's
* read_some function.
*
* @param s The stream from which the data is to be read. The type must support
* the Sync_Read_Stream concept.
*
* @param b The basic_streambuf object into which the data will be read.
*
* @param completion_condition The function object to be called to determine
* whether the read operation is complete. The signature of the function object
* must be:
* @code bool completion_condition(
* const Sync_Read_Stream::error_type& error, // Result of latest read_some
* // operation.
*
* std::size_t bytes_transferred // Number of bytes transferred
* // so far.
* ); @endcode
* A return value of true indicates that the read operation is complete. False
* indicates that further calls to the stream's read_some function are required.
*
* @returns The number of bytes transferred.
*
* @throws Sync_Read_Stream::error_type Thrown on failure.
*
* @note This overload is equivalent to calling:
* @code asio::read(
* s, b, completion_condition,
* asio::throw_error()); @endcode
*/
template <typename Sync_Read_Stream, typename Allocator,
typename Completion_Condition>
std::size_t read(Sync_Read_Stream& s, basic_streambuf<Allocator>& b,
Completion_Condition completion_condition);
/// Attempt to read a certain amount of data from a stream before returning.
/**
* This function is used to read a certain number of bytes of data from a
* stream. The call will block until one of the following conditions is true:
*
* @li The completion_condition function object returns true.
*
* This operation is implemented in terms of one or more calls to the stream's
* read_some function.
*
* @param s The stream from which the data is to be read. The type must support
* the Sync_Read_Stream concept.
*
* @param b The basic_streambuf object into which the data will be read.
*
* @param completion_condition The function object to be called to determine
* whether the read operation is complete. The signature of the function object
* must be:
* @code bool completion_condition(
* const Sync_Read_Stream::error_type& error, // Result of latest read_some
* // operation.
*
* std::size_t bytes_transferred // Number of bytes transferred
* // so far.
* ); @endcode
* A return value of true indicates that the read operation is complete. False
* indicates that further calls to the stream's read_some function are required.
*
* @param error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const Sync_Read_Stream::error_type& error // Result of operation.
* ); @endcode
* The error handler is only called if the completion_condition indicates that
* the operation is complete.
*
* @returns The number of bytes read. If an error occurs, and the error handler
* does not throw an exception, returns the total number of bytes successfully
* transferred prior to the error.
*/
template <typename Sync_Read_Stream, typename Allocator,
typename Completion_Condition, typename Error_Handler>
std::size_t read(Sync_Read_Stream& s, basic_streambuf<Allocator>& b,
Completion_Condition completion_condition, Error_Handler error_handler);
/*@}*/
/**
* @defgroup async_read asio::async_read
@ -313,6 +431,111 @@ template <typename Async_Read_Stream, typename Mutable_Buffers,
void async_read(Async_Read_Stream& s, const Mutable_Buffers& buffers,
Completion_Condition completion_condition, Handler handler);
/// Start an asynchronous operation to read a certain amount of data from a
/// stream.
/**
* This function is used to asynchronously read a certain number of bytes of
* data from a stream. The function call always returns immediately. The
* asynchronous operation will continue until one of the following conditions is
* true:
*
* @li An error occurred.
*
* @param s The stream from which the data is to be read. The type must support
* the Async_Read_Stream concept.
*
* This operation is implemented in terms of one or more calls to the stream's
* async_read_some function.
*
* @param b A basic_streambuf object into which the data will be read. Ownership
* of the streambuf is retained by the caller, which must guarantee that it
* remains valid until the handler is called.
*
* @param handler The handler to be called when the read operation completes.
* Copies will be made of the handler as required. The function signature of the
* handler must be:
* @code void handler(
* const Async_Read_Stream::error_type& error, // Result of operation.
*
* std::size_t bytes_transferred // Number of bytes copied into
* // the buffers. If an error
* // occurred, this will be the
* // number of bytes successfully
* // transferred prior to the
* // error.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*
* @note This overload is equivalent to calling:
* @code asio::async_read(
* s, b,
* asio::transfer_all(),
* handler); @endcode
*/
template <typename Async_Read_Stream, typename Allocator, typename Handler>
void async_read(Async_Read_Stream& s, basic_streambuf<Allocator>& b,
Handler handler);
/// Start an asynchronous operation to read a certain amount of data from a
/// stream.
/**
* This function is used to asynchronously read a certain number of bytes of
* data from a stream. The function call always returns immediately. The
* asynchronous operation will continue until one of the following conditions is
* true:
*
* @li The completion_condition function object returns true.
*
* This operation is implemented in terms of one or more calls to the stream's
* async_read_some function.
*
* @param s The stream from which the data is to be read. The type must support
* the Async_Read_Stream concept.
*
* @param b A basic_streambuf object into which the data will be read. Ownership
* of the streambuf is retained by the caller, which must guarantee that it
* remains valid until the handler is called.
*
* @param completion_condition The function object to be called to determine
* whether the read operation is complete. The signature of the function object
* must be:
* @code bool completion_condition(
* const Async_Read_Stream::error_type& error, // Result of latest read_some
* // operation.
*
* std::size_t bytes_transferred // Number of bytes transferred
* // so far.
* ); @endcode
* A return value of true indicates that the read operation is complete. False
* indicates that further calls to the stream's async_read_some function are
* required.
*
* @param handler The handler to be called when the read operation completes.
* Copies will be made of the handler as required. The function signature of the
* handler must be:
* @code void handler(
* const Async_Read_Stream::error_type& error, // Result of operation.
*
* std::size_t bytes_transferred // Number of bytes copied into
* // the buffers. If an error
* // occurred, this will be the
* // number of bytes successfully
* // transferred prior to the
* // error.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*/
template <typename Async_Read_Stream, typename Allocator,
typename Completion_Condition, typename Handler>
void async_read(Async_Read_Stream& s, basic_streambuf<Allocator>& b,
Completion_Condition completion_condition, Handler handler);
/*@}*/
} // namespace asio

View File

@ -49,7 +49,7 @@ namespace asio {
* @param s The stream from which the data is to be read. The type must support
* the Sync_Read_Stream concept.
*
* @param b A streambuf object into which the data will be written.
* @param b A streambuf object into which the data will be read.
*
* @param delim The delimiter character.
*
@ -92,7 +92,7 @@ std::size_t read_until(Sync_Read_Stream& s,
* @param s The stream from which the data is to be read. The type must support
* the Sync_Read_Stream concept.
*
* @param b A streambuf object into which the data will be written.
* @param b A streambuf object into which the data will be read.
*
* @param delim The delimiter character.
*
@ -131,7 +131,7 @@ std::size_t read_until(Sync_Read_Stream& s,
* @param s The stream from which the data is to be read. The type must support
* the Sync_Read_Stream concept.
*
* @param b A streambuf object into which the data will be written.
* @param b A streambuf object into which the data will be read.
*
* @param expr The regular expression.
*
@ -174,7 +174,7 @@ std::size_t read_until(Sync_Read_Stream& s,
* @param s The stream from which the data is to be read. The type must support
* the Sync_Read_Stream concept.
*
* @param b A streambuf object into which the data will be written.
* @param b A streambuf object into which the data will be read.
*
* @param expr The regular expression.
*
@ -188,17 +188,17 @@ std::size_t read_until(Sync_Read_Stream& s,
* the operation is complete.
*
* @returns The number of bytes in the streambuf's get area up to and including
* the substring that matches the regular expression.
*/
* the substring that matches the regular expression.
*/
template <typename Sync_Read_Stream, typename Allocator, typename Error_Handler>
std::size_t read_until(Sync_Read_Stream& s,
asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
Error_Handler error_handler);
asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
Error_Handler error_handler);
/*@}*/
/**
* @defgroup async_read_until asio::async_read_until
*/
* @defgroup async_read_until asio::async_read_until
*/
/*@{*/
/// Start an asynchronous operation to read data into a streambuf until a
@ -220,7 +220,7 @@ std::size_t read_until(Sync_Read_Stream& s,
* @param s The stream from which the data is to be read. The type must support
* the Async_Read_Stream concept.
*
* @param b A streambuf object into which the data will be written. Ownership of
* @param b A streambuf object into which the data will be read. Ownership of
* the streambuf is retained by the caller, which must guarantee that it remains
* valid until the handler is called.
*
@ -261,7 +261,7 @@ std::size_t read_until(Sync_Read_Stream& s,
*/
template <typename Async_Read_Stream, typename Allocator, typename Handler>
void async_read_until(Async_Read_Stream& s,
asio::basic_streambuf<Allocator>& b, char delim, Handler handler);
asio::basic_streambuf<Allocator>& b, char delim, Handler handler);
/// Start an asynchronous operation to read data into a streambuf until a
/// regular expression is located.
@ -283,7 +283,7 @@ void async_read_until(Async_Read_Stream& s,
* @param s The stream from which the data is to be read. The type must support
* the Async_Read_Stream concept.
*
* @param b A streambuf object into which the data will be written. Ownership of
* @param b A streambuf object into which the data will be read. Ownership of
* the streambuf is retained by the caller, which must guarantee that it remains
* valid until the handler is called.
*

View File

@ -22,6 +22,8 @@
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/basic_streambuf.hpp"
namespace asio {
/**
@ -176,6 +178,129 @@ template <typename Sync_Write_Stream, typename Const_Buffers,
std::size_t write(Sync_Write_Stream& s, const Const_Buffers& buffers,
Completion_Condition completion_condition, Error_Handler error_handler);
/// Write a certain amount of data to a stream before returning.
/**
* This function is used to write a certain number of bytes of data to a stream.
* The call will block until one of the following conditions is true:
*
* @li All of the data in the supplied basic_streambuf has been written.
*
* @li An error occurred.
*
* This operation is implemented in terms of one or more calls to the stream's
* write_some function.
*
* @param s The stream to which the data is to be written. The type must support
* the Sync_Write_Stream concept.
*
* @param b The basic_streambuf object from which data will be written.
*
* @returns The number of bytes transferred.
*
* @throws Sync_Write_Stream::error_type Thrown on failure.
*
* @note This overload is equivalent to calling:
* @code asio::write(
* s, b,
* asio::transfer_all(),
* asio::throw_error()); @endcode
*/
template <typename Sync_Write_Stream, typename Allocator>
std::size_t write(Sync_Write_Stream& s, basic_streambuf<Allocator>& b);
/// Write a certain amount of data to a stream before returning.
/**
* This function is used to write a certain number of bytes of data to a stream.
* The call will block until one of the following conditions is true:
*
* @li All of the data in the supplied basic_streambuf has been written.
*
* @li The completion_condition function object returns true.
*
* This operation is implemented in terms of one or more calls to the stream's
* write_some function.
*
* @param s The stream to which the data is to be written. The type must support
* the Sync_Write_Stream concept.
*
* @param b The basic_streambuf object from which data will be written.
*
* @param completion_condition The function object to be called to determine
* whether the write operation is complete. The signature of the function object
* must be:
* @code bool completion_condition(
* const Sync_Write_Stream::error_type& error, // Result of latest write_some
* // operation.
*
* std::size_t bytes_transferred // Number of bytes transferred
* // so far.
* ); @endcode
* A return value of true indicates that the write operation is complete. False
* indicates that further calls to the stream's write_some function are
* required.
*
* @returns The number of bytes transferred.
*
* @throws Sync_Write_Stream::error_type Thrown on failure.
*
* @note This overload is equivalent to calling:
* @code asio::write(
* s, b,
* completion_condition,
* asio::throw_error()); @endcode
*/
template <typename Sync_Write_Stream, typename Allocator,
typename Completion_Condition>
std::size_t write(Sync_Write_Stream& s, basic_streambuf<Allocator>& b,
Completion_Condition completion_condition);
/// Write a certain amount of data to a stream before returning.
/**
* This function is used to write a certain number of bytes of data to a stream.
* The call will block until one of the following conditions is true:
*
* @li All of the data in the supplied basic_streambuf has been written.
*
* @li The completion_condition function object returns true.
*
* This operation is implemented in terms of one or more calls to the stream's
* write_some function.
*
* @param s The stream to which the data is to be written. The type must support
* the Sync_Write_Stream concept.
*
* @param b The basic_streambuf object from which data will be written.
*
* @param completion_condition The function object to be called to determine
* whether the write operation is complete. The signature of the function object
* must be:
* @code bool completion_condition(
* const Sync_Write_Stream::error_type& error, // Result of latest write_some
* // operation.
*
* std::size_t bytes_transferred // Number of bytes transferred
* // so far.
* ); @endcode
* A return value of true indicates that the write operation is complete. False
* indicates that further calls to the stream's write_some function are
* required.
*
* @param error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const Sync_Write_Stream::error_type& error // Result of operation.
* ); @endcode
*
* @returns The number of bytes written. If an error occurs, and the error
* handler does not throw an exception, returns the total number of bytes
* successfully transferred prior to the error.
*/
template <typename Sync_Write_Stream, typename Allocator,
typename Completion_Condition, typename Error_Handler>
std::size_t write(Sync_Write_Stream& s, basic_streambuf<Allocator>& b,
Completion_Condition completion_condition, Error_Handler error_handler);
/*@}*/
/**
* @defgroup async_write asio::async_write
@ -306,6 +431,107 @@ template <typename Async_Write_Stream, typename Const_Buffers,
void async_write(Async_Write_Stream& s, const Const_Buffers& buffers,
Completion_Condition completion_condition, Handler handler);
/// Start an asynchronous operation to write a certain amount of data to a
/// stream.
/**
* This function is used to asynchronously write a certain number of bytes of
* data to a stream. The function call always returns immediately. The
* asynchronous operation will continue until one of the following conditions
* is true:
*
* @li All of the data in the supplied basic_streambuf has been written.
*
* @li An error occurred.
*
* This operation is implemented in terms of one or more calls to the stream's
* async_write_some function.
*
* @param s The stream to which the data is to be written. The type must support
* the Async_Write_Stream concept.
*
* @param b A basic_streambuf object from which data will be written. Ownership
* of the streambuf is retained by the caller, which must guarantee that it
* remains valid until the handler is called.
*
* @param handler The handler to be called when the write operation completes.
* Copies will be made of the handler as required. The function signature of the
* handler must be:
* @code void handler(
* const Async_Write_Stream::error_type& error, // Result of operation.
*
* std::size_t bytes_transferred // Number of bytes written
* // from the buffers. If an
* // error occurred, this will
* // be less than the sum of the
* // buffer sizes.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*/
template <typename Async_Write_Stream, typename Allocator, typename Handler>
void async_write(Async_Write_Stream& s, basic_streambuf<Allocator>& b,
Handler handler);
/// Start an asynchronous operation to write a certain amount of data to a
/// stream.
/**
* This function is used to asynchronously write a certain number of bytes of
* data to a stream. The function call always returns immediately. The
* asynchronous operation will continue until one of the following conditions
* is true:
*
* @li All of the data in the supplied basic_streambuf has been written.
*
* @li The completion_condition function object returns true.
*
* This operation is implemented in terms of one or more calls to the stream's
* async_write_some function.
*
* @param s The stream to which the data is to be written. The type must support
* the Async_Write_Stream concept.
*
* @param b A basic_streambuf object from which data will be written. Ownership
* of the streambuf is retained by the caller, which must guarantee that it
* remains valid until the handler is called.
*
* @param completion_condition The function object to be called to determine
* whether the write operation is complete. The signature of the function object
* must be:
* @code bool completion_condition(
* const Async_Write_Stream::error_type& error, // Result of latest write_some
* // operation.
*
* std::size_t bytes_transferred // Number of bytes transferred
* // so far.
* ); @endcode
* A return value of true indicates that the write operation is complete. False
* indicates that further calls to the stream's async_write_some function are
* required.
*
* @param handler The handler to be called when the write operation completes.
* Copies will be made of the handler as required. The function signature of the
* handler must be:
* @code void handler(
* const Async_Write_Stream::error_type& error, // Result of operation.
*
* std::size_t bytes_transferred // Number of bytes written
* // from the buffers. If an
* // error occurred, this will
* // be less than the sum of the
* // buffer sizes.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
* asio::io_service::post().
*/
template <typename Async_Write_Stream, typename Allocator,
typename Completion_Condition, typename Handler>
void async_write(Async_Write_Stream& s, basic_streambuf<Allocator>& b,
Completion_Condition completion_condition, Handler handler);
/*@}*/
} // namespace asio