Convert buffered_read_stream to use multiple buffers.
This commit is contained in:
parent
a254c2bf18
commit
1066ee2462
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user