Convert buffered_read_stream to use multiple buffers.

This commit is contained in:
chris_kohlhoff 2005-09-10 00:28:23 +00:00
parent a254c2bf18
commit 1066ee2462

View File

@ -18,12 +18,15 @@
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <cstring>
#include <boost/config.hpp>
#include <boost/noncopyable.hpp>
#include <boost/type_traits.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/buffered_read_stream_fwd.hpp"
#include "asio/buffers.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/buffer_resize_guard.hpp"
@ -99,37 +102,39 @@ public:
/// Write the given data to the stream. Returns the number of bytes written or
/// 0 if the stream was closed cleanly. Throws an exception on failure.
size_t write(const void* data, size_t length)
template <typename Const_Buffers>
std::size_t write(const Const_Buffers& buffers)
{
return next_layer_.write(data, length);
return next_layer_.write(buffers);
}
/// Write the given data to the stream. Returns the number of bytes written or
/// 0 if the stream was closed cleanly.
template <typename Error_Handler>
size_t write(const void* data, size_t length, Error_Handler error_handler)
template <typename Const_Buffers, typename Error_Handler>
std::size_t write(const Const_Buffers& buffers, Error_Handler error_handler)
{
return next_layer_.write(data, length, error_handler);
return next_layer_.write(buffers, error_handler);
}
/// Start an asynchronous write. The data being written must be valid for the
/// lifetime of the asynchronous operation.
template <typename Handler>
void async_write(const void* data, size_t length, Handler handler)
template <typename Const_Buffers, typename Handler>
void async_write(const Const_Buffers& buffers, Handler handler)
{
next_layer_.async_write(data, length, handler);
next_layer_.async_write(buffers, handler);
}
/// Fill the buffer with some data. Returns the number of bytes placed in the
/// buffer as a result of the operation, or 0 if the underlying stream was
/// closed. Throws an exception on failure.
size_t fill()
std::size_t fill()
{
detail::buffer_resize_guard<Buffer> resize_guard(buffer_);
size_t previous_size = buffer_.size();
std::size_t previous_size = buffer_.size();
buffer_.resize(buffer_.capacity());
buffer_.resize(previous_size + next_layer_.read(
buffer_.begin() + previous_size, buffer_.size() - previous_size));
buffer_.resize(previous_size + next_layer_.read(buffers(
buffer_.begin() + previous_size,
buffer_.size() - previous_size)));
resize_guard.commit();
return buffer_.size() - previous_size;
}
@ -138,13 +143,14 @@ public:
/// buffer as a result of the operation, or 0 if the underlying stream was
/// closed.
template <typename Error_Handler>
size_t fill(Error_Handler error_handler)
std::size_t fill(Error_Handler error_handler)
{
detail::buffer_resize_guard<Buffer> resize_guard(buffer_);
size_t previous_size = buffer_.size();
std::size_t previous_size = buffer_.size();
buffer_.resize(buffer_.capacity());
buffer_.resize(previous_size + next_layer_.read(
buffer_.begin() + previous_size, buffer_.size() - previous_size,
buffer_.resize(previous_size + next_layer_.read(buffers(
buffer_.begin() + previous_size,
buffer_.size() - previous_size),
error_handler));
resize_guard.commit();
return buffer_.size() - previous_size;
@ -155,7 +161,7 @@ public:
{
public:
fill_handler(buffered_read_stream<Stream, Buffer>& stream,
size_t previous_size, Handler handler)
std::size_t previous_size, Handler handler)
: stream_(stream),
previous_size_(previous_size),
handler_(handler)
@ -163,16 +169,16 @@ public:
}
template <typename Error>
void operator()(const Error& e, size_t bytes_readd)
void operator()(const Error& e, std::size_t bytes_transferred)
{
stream_.read_buffer().resize(previous_size_ + bytes_readd);
stream_.read_buffer().resize(previous_size_ + bytes_transferred);
stream_.demuxer().dispatch(
detail::bind_handler(handler_, e, bytes_readd));
detail::bind_handler(handler_, e, bytes_transferred));
}
private:
buffered_read_stream<Stream, Buffer>& stream_;
size_t previous_size_;
std::size_t previous_size_;
Handler handler_;
};
@ -180,116 +186,133 @@ public:
template <typename Handler>
void async_fill(Handler handler)
{
size_t previous_size = buffer_.size();
std::size_t previous_size = buffer_.size();
buffer_.resize(buffer_.capacity());
next_layer_.async_read(buffer_.begin() + previous_size,
buffer_.size() - previous_size,
next_layer_.async_read(
buffers(
buffer_.begin() + previous_size,
buffer_.size() - previous_size),
fill_handler<Handler>(*this, previous_size, handler));
}
/// Read some data from the stream. Returns the number of bytes read or 0 if
/// the stream was closed cleanly. Throws an exception on failure.
size_t read(void* data, size_t max_length)
template <typename Mutable_Buffers>
std::size_t read(const Mutable_Buffers& buffers)
{
if (buffer_.empty() && !fill())
return 0;
return copy(data, max_length);
return copy(buffers);
}
/// Read some data from the stream. Returns the number of bytes read or 0 if
/// the stream was closed cleanly.
template <typename Error_Handler>
size_t read(void* data, size_t max_length, Error_Handler error_handler)
template <typename Mutable_Buffers, typename Error_Handler>
std::size_t read(const Mutable_Buffers& buffers, Error_Handler error_handler)
{
if (buffer_.empty() && !fill(error_handler))
return 0;
return copy(data, max_length);
return copy(buffers);
}
template <typename Handler>
template <typename Mutable_Buffers, typename Handler>
class read_handler
{
public:
read_handler(buffered_read_stream<Stream, Buffer>& stream, void* data,
size_t max_length, Handler handler)
read_handler(buffered_read_stream<Stream, Buffer>& stream,
const Mutable_Buffers& buffers, Handler handler)
: stream_(stream),
data_(data),
max_length_(max_length),
buffers_(buffers),
handler_(handler)
{
}
template <typename Error>
void operator()(const Error& e, size_t bytes_readd)
void operator()(const Error& e, std::size_t bytes_transferred)
{
if (e || stream_.read_buffer().empty())
{
size_t length = 0;
std::size_t length = 0;
stream_.demuxer().dispatch(detail::bind_handler(handler_, e, length));
}
else
{
using namespace std; // For memcpy.
size_t bytes_avail = stream_.read_buffer().size();
size_t length = (max_length_ < bytes_avail)
? max_length_ : bytes_avail;
memcpy(data_, stream_.read_buffer().begin(), length);
stream_.read_buffer().pop(length);
stream_.demuxer().dispatch(detail::bind_handler(handler_, e, length));
std::size_t bytes_avail = stream_.read_buffer().size();
std::size_t bytes_copied = 0;
typename Mutable_Buffers::const_iterator iter = buffers_.begin();
typename Mutable_Buffers::const_iterator end = buffers_.end();
for (; iter != end && bytes_avail > 0; ++iter)
{
std::size_t max_length = iter->size();
std::size_t length = (max_length < bytes_avail)
? max_length : bytes_avail;
memcpy(iter->data(),
stream_.read_buffer().begin() + bytes_copied, length);
bytes_copied += length;
bytes_avail -= length;
}
stream_.read_buffer().pop(bytes_copied);
stream_.demuxer().dispatch(
detail::bind_handler(handler_, e, bytes_copied));
}
}
private:
buffered_read_stream<Stream, Buffer>& stream_;
void* data_;
size_t max_length_;
Mutable_Buffers buffers_;
Handler handler_;
};
/// Start an asynchronous read. The buffer into which the data will be read
/// must be valid for the lifetime of the asynchronous operation.
template <typename Handler>
void async_read(void* data, size_t max_length, Handler handler)
template <typename Mutable_Buffers, typename Handler>
void async_read(const Mutable_Buffers& buffers, Handler handler)
{
if (buffer_.empty())
{
async_fill(read_handler<Handler>(*this, data, max_length, handler));
async_fill(read_handler<Mutable_Buffers, Handler>(
*this, buffers, handler));
}
else
{
size_t length = copy(data, max_length);
next_layer_.demuxer().post(detail::bind_handler(handler, 0, length));
std::size_t length = copy(buffers);
demuxer().post(detail::bind_handler(handler, 0, length));
}
}
/// Peek at the incoming data on the stream. Returns the number of bytes read
/// or 0 if the stream was closed cleanly.
size_t peek(void* data, size_t max_length)
template <typename Mutable_Buffers>
std::size_t peek(const Mutable_Buffers& buffers)
{
if (buffer_.empty() && !fill())
return 0;
return peek_copy(data, max_length);
return peek_copy(buffers);
}
/// Peek at the incoming data on the stream. Returns the number of bytes read
/// or 0 if the stream was closed cleanly.
template <typename Error_Handler>
size_t peek(void* data, size_t max_length, Error_Handler error_handler)
template <typename Mutable_Buffers, typename Error_Handler>
std::size_t peek(const Mutable_Buffers& buffers, Error_Handler error_handler)
{
if (buffer_.empty() && !fill(error_handler))
return 0;
return peek_copy(data, max_length);
return peek_copy(buffers);
}
/// Determine the amount of data that may be read without blocking.
size_t in_avail()
std::size_t in_avail()
{
return buffer_.size();
}
/// Determine the amount of data that may be read without blocking.
template <typename Error_Handler>
size_t in_avail(Error_Handler error_handler)
std::size_t in_avail(Error_Handler error_handler)
{
return buffer_.size();
}
@ -297,30 +320,54 @@ public:
private:
/// Copy data out of the internal buffer to the specified target buffer.
/// Returns the number of bytes copied.
size_t copy(void* data, size_t max_length)
template <typename Mutable_Buffers>
std::size_t copy(const Mutable_Buffers& buffers)
{
using namespace std; // For memcpy.
size_t bytes_avail = buffer_.size();
size_t length = (max_length < bytes_avail) ? max_length : bytes_avail;
memcpy(data, buffer_.begin(), length);
buffer_.pop(length);
std::size_t bytes_avail = buffer_.size();
std::size_t bytes_copied = 0;
return length;
typename Mutable_Buffers::const_iterator iter = buffers.begin();
typename Mutable_Buffers::const_iterator end = buffers.end();
for (; iter != end && bytes_avail > 0; ++iter)
{
std::size_t max_length = iter->size();
std::size_t length = (max_length < bytes_avail)
? max_length : bytes_avail;
memcpy(iter->data(), buffer_.begin() + bytes_copied, length);
bytes_copied += length;
bytes_avail -= length;
}
buffer_.pop(bytes_copied);
return bytes_copied;
}
/// Copy data from the internal buffer to the specified target buffer, without
/// removing the data from the internal buffer. Returns the number of bytes
/// copied.
size_t peek_copy(void* data, size_t max_length)
template <typename Mutable_Buffers>
std::size_t peek_copy(const Mutable_Buffers& buffers)
{
using namespace std; // For memcpy.
size_t bytes_avail = buffer_.size();
size_t length = (max_length < bytes_avail) ? max_length : bytes_avail;
memcpy(data, buffer_.begin(), length);
std::size_t bytes_avail = buffer_.size();
std::size_t bytes_copied = 0;
return length;
typename Mutable_Buffers::const_iterator iter = buffers.begin();
typename Mutable_Buffers::const_iterator end = buffers.end();
for (; iter != end && bytes_avail > 0; ++iter)
{
std::size_t max_length = iter->size();
std::size_t length = (max_length < bytes_avail)
? max_length : bytes_avail;
memcpy(iter->data(), buffer_.begin() + bytes_copied, length);
bytes_copied += length;
bytes_avail -= length;
}
return bytes_copied;
}
/// The next layer.