Remove recv_decode and friends, in anticipation of a new improved way of

writing message decoders.
This commit is contained in:
chris 2004-05-07 02:12:16 +00:00
parent e54ba39147
commit 92414c7e63
2 changed files with 0 additions and 411 deletions

View File

@ -6,16 +6,6 @@ Add vectored send/recv functions
Add the sendv and recvv functions to basic_stream_socket and presumably also to Add the sendv and recvv functions to basic_stream_socket and presumably also to
the buffered stream templates. the buffered stream templates.
Add encode_send/async_encode_send functions
-------------------------------------------
Add new free functions encode_send/async_encode_send that mirror the
functionality of recv_decode/async_recv_decode.
Develop a safe version of recv_until
------------------------------------
The current implementation of recv_until (and async_recv_until) does not set
an upper limit on the size of the received data. This is not particularly safe.
Demuxer functions for event loop integration Demuxer functions for event loop integration
-------------------------------------------- --------------------------------------------
Add functions demuxer::work_pending() and demuxer::perform_work() that can be Add functions demuxer::work_pending() and demuxer::perform_work() that can be

View File

@ -17,11 +17,6 @@
#include "asio/detail/push_options.hpp" #include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <string>
#include <utility>
#include "asio/detail/pop_options.hpp"
#include "asio/detail/bind_handler.hpp" #include "asio/detail/bind_handler.hpp"
namespace asio { namespace asio {
@ -479,402 +474,6 @@ inline void async_recv_at_least_n(Stream& s, void* data, size_t min_length,
max_length, handler)); max_length, handler));
} }
/// Read some data from a stream and decode it.
/**
* This function is used to receive data on a stream and decode it in a single
* operation. The function call will block until the decoder function object
* indicates that it has finished.
*
* @param s The stream on which the data is to be received.
*
* @param decoder The decoder function object to be called to decode the
* received data. The function object is assumed to be stateful. That is, it
* may not be given sufficient data in a single invocation to complete
* decoding, and is expected to maintain state so that it may resume decoding
* when the next piece of data is supplied. Copies will be made of the decoder
* function object as required, however with respect to maintaining state it
* can rely on the fact that only an up-to-date copy will be used. The
* equivalent function signature of the handler must be:
* @code std::pair<bool, const char*> decoder(
* const char* begin, // Pointer to the beginning of data to be decoded.
* const char* end // Pointer to one-past-the-end of data to be decoded.
* ); @endcode
* The first element of the return value is true if the decoder has finished.
* The second element is a pointer to the beginning of the unused portion of
* the data.
*
* @param total_bytes_recvd An optional output parameter that receives the
* total number of bytes actually received.
*
* @returns The number of bytes received on the last recv, or 0 if end-of-file
* was reached or the connection was closed cleanly.
*
* @note Throws an exception on failure. The type of the exception depends
* on the underlying stream's recv operation.
*/
template <typename Buffered_Stream, typename Decoder>
size_t recv_decode(Buffered_Stream& s, Decoder decoder,
size_t* total_bytes_recvd = 0)
{
size_t total_recvd = 0;
for (;;)
{
if (s.recv_buffer().empty() && s.fill() == 0)
{
if (total_bytes_recvd)
*total_bytes_recvd = total_recvd;
return 0;
}
std::pair<bool, const char*> result =
decoder(s.recv_buffer().begin(), s.recv_buffer().end());
size_t bytes_read = result.second - s.recv_buffer().begin();
s.recv_buffer().pop(bytes_read);
total_recvd += bytes_read;
if (result.first)
{
if (total_bytes_recvd)
*total_bytes_recvd = total_recvd;
return bytes_read;
}
}
}
/// Read some data from a stream and decode it.
/**
* This function is used to receive data on a stream and decode it in a single
* operation. The function call will block until the decoder function object
* indicates that it has finished.
*
* @param s The stream on which the data is to be received.
*
* @param decoder The decoder function object to be called to decode the
* received data. The function object is assumed to be stateful. That is, it
* may not be given sufficient data in a single invocation to complete
* decoding, and is expected to maintain state so that it may resume decoding
* when the next piece of data is supplied. Copies will be made of the decoder
* function object as required, however with respect to maintaining state it
* can rely on the fact that only an up-to-date copy will be used. The
* equivalent function signature of the handler must be:
* @code std::pair<bool, const char*> decoder(
* const char* begin, // Pointer to the beginning of data to be decoded.
* const char* end // Pointer to one-past-the-end of data to be decoded.
* ); @endcode
* The first element of the return value is true if the decoder has finished.
* The second element is a pointer to the beginning of the unused portion of
* the data.
*
* @param total_bytes_recvd An optional output parameter that receives the
* total number of bytes actually received.
*
* @param error_handler The handler to be called when an error occurs. Copies
* will be made of the handler as required. The equivalent function signature
* of the handler must be:
* @code template <typename Error>
* void error_handler(
* const Error& error // Result of operation (the actual type is dependent on
* // the underlying stream's recv operation)
* ); @endcode
*
* @returns The number of bytes received on the last recv, or 0 if end-of-file
* was reached or the connection was closed cleanly.
*/
template <typename Buffered_Stream, typename Decoder, typename Error_Handler>
size_t recv_decode(Buffered_Stream& s, Decoder decoder,
size_t* total_bytes_recvd, Error_Handler error_handler)
{
size_t total_recvd = 0;
for (;;)
{
if (s.recv_buffer().empty() && s.fill(error_handler) == 0)
{
if (total_bytes_recvd)
*total_bytes_recvd = total_recvd;
return 0;
}
std::pair<bool, const char*> result =
decoder(s.recv_buffer().begin(), s.recv_buffer().end());
size_t bytes_read = result.second - s.recv_buffer().begin();
s.recv_buffer().pop(bytes_read);
total_recvd += bytes_read;
if (result.first)
{
if (total_bytes_recvd)
*total_bytes_recvd = total_recvd;
return bytes_read;
}
}
}
namespace detail
{
template <typename Buffered_Stream, typename Decoder, typename Handler>
class recv_decode_handler
{
public:
recv_decode_handler(Buffered_Stream& stream, Decoder decoder,
Handler handler)
: stream_(stream),
decoder_(decoder),
total_recvd_(0),
handler_(handler)
{
}
template <typename Error>
void operator()(const Error& e, size_t bytes_recvd)
{
if (e || bytes_recvd == 0)
{
stream_.demuxer().dispatch(
detail::bind_handler(handler_, e, bytes_recvd, total_recvd_));
}
else
{
while (!stream_.recv_buffer().empty())
{
std::pair<bool, const char*> result =
decoder_(stream_.recv_buffer().begin(),
stream_.recv_buffer().end());
size_t bytes_read = result.second - stream_.recv_buffer().begin();
stream_.recv_buffer().pop(bytes_read);
total_recvd_ += bytes_read;
if (result.first)
{
stream_.demuxer().dispatch(
detail::bind_handler(handler_, 0, bytes_read, total_recvd_));
return;
}
}
stream_.async_fill(*this);
}
}
private:
Buffered_Stream& stream_;
Decoder decoder_;
size_t total_recvd_;
Handler handler_;
};
} // namespace detail
/// Start an asynchronous receive that will not complete until some data has
/// been fully decoded.
/**
* This function is used to receive data on a stream and decode it in a single
* asynchronous operation. The function call always returns immediately. The
* asynchronous operation will complete only when the decoder indicates that it
* has finished.
*
* @param s The stream on which the data is to be received.
*
* @param decoder The decoder function object to be called to decode the
* received data. The function object is assumed to be stateful. That is, it
* may not be given sufficient data in a single invocation to complete
* decoding, and is expected to maintain state so that it may resume decoding
* when the next piece of data is supplied. Copies will be made of the decoder
* function object as required, however with respect to maintaining state it
* can rely on the fact that only an up-to-date copy will be used. The
* equivalent function signature of the handler must be:
* @code std::pair<bool, const char*> decoder(
* const char* begin, // Pointer to the beginning of data to be decoded.
* const char* end // Pointer to one-past-the-end of data to be decoded.
* ); @endcode
* The first element of the return value is true if the decoder has finished.
* The second element is a pointer to the beginning of the unused portion of
* the data.
*
* @param handler The handler to be called when the receive operation
* completes. Copies will be made of the handler as required. The equivalent
* function signature of the handler must be:
* @code template <typename Error>
* void handler(
* const Error& error, // Result of operation (the actual type is
* // dependent on the underlying stream's recv
* // operation)
* size_t last_bytes_recvd, // Number of bytes received on last recv
* // operation
* size_t total_bytes_recvd // Total number of bytes successfully received
* ); @endcode
*/
template <typename Buffered_Stream, typename Decoder, typename Handler>
void async_recv_decode(Buffered_Stream& s, Decoder decoder, Handler handler)
{
while (!s.recv_buffer().empty())
{
std::pair<bool, const char*> result =
decoder(s.recv_buffer().begin(), s.recv_buffer().end());
size_t bytes_read = result.second - s.recv_buffer().begin();
s.recv_buffer().pop(bytes_read);
if (result.first)
{
s.demuxer().post(
detail::bind_handler(handler, 0, bytes_read, bytes_read));
return;
}
}
s.async_fill(detail::recv_decode_handler<Buffered_Stream, Decoder, Handler>(
s, decoder, handler));
}
namespace detail
{
class recv_until_decoder
{
public:
recv_until_decoder(std::string& data, const std::string& delimiter)
: data_(data),
delimiter_(delimiter),
delimiter_length_(delimiter.length()),
delimiter_pos_(0)
{
data_ = "";
}
std::pair<bool, const char*> operator()(const char* begin, const char* end)
{
const char* p = begin;
while (p < end)
{
char next_char = *p++;
if (next_char == delimiter_[delimiter_pos_])
{
if (++delimiter_pos_ == delimiter_length_)
{
data_.append(begin, p - begin);
return std::make_pair(true, p);
}
}
else
{
delimiter_pos_ = 0;
}
}
data_.append(begin, end - begin);
return std::make_pair(false, end);
}
private:
std::string& data_;
std::string delimiter_;
size_t delimiter_length_;
size_t delimiter_pos_;
};
}
/// Read data from the stream until a delimiter is reached.
/**
* This function is used to receive data from the stream into a std::string
* object until a specified delimiter is reached. The function call will block
* until the delimiter is found or an error occurs.
*
* @param s The stream on which the data is to be received.
*
* @param data The std::string object into which the received data will be
* written.
*
* @param delimiter The pattern marking the end of the data to receive.
*
* @param total_bytes_recvd An optional output parameter that receives the
* total number of bytes actually received.
*
* @returns The number of bytes received on the last recv, or 0 if end-of-file
* was reached or the connection was closed cleanly.
*
* @note Throws an exception on failure. The type of the exception depends
* on the underlying stream's recv operation.
*/
template <typename Buffered_Stream>
inline size_t recv_until(Buffered_Stream& s, std::string& data,
const std::string& delimiter, size_t* total_bytes_recvd = 0)
{
return recv_decode(s, detail::recv_until_decoder(data, delimiter),
total_bytes_recvd);
}
/// Read data from the stream until a delimiter is reached.
/**
* This function is used to receive data from the stream into a std::string
* object until a specified delimiter is reached. The function call will block
* until the delimiter is found or an error occurs.
*
* @param s The stream on which the data is to be received.
*
* @param data The std::string object into which the received data will be
* written.
*
* @param delimiter The pattern marking the end of the data to receive.
*
* @param total_bytes_recvd An optional output parameter that receives the
* total number of bytes actually received.
*
* @param error_handler The handler to be called when an error occurs. Copies
* will be made of the handler as required. The equivalent function signature
* of the handler must be:
* @code template <typename Error>
* void error_handler(
* const Error& error // Result of operation (the actual type is dependent on
* // the underlying stream's recv operation)
* ); @endcode
*
* @returns The number of bytes received on the last recv, or 0 if end-of-file
* was reached or the connection was closed cleanly.
*/
template <typename Buffered_Stream, typename Error_Handler>
inline size_t recv_until(Buffered_Stream& s, std::string& data,
const std::string& delimiter, size_t* total_bytes_recvd,
Error_Handler error_handler)
{
return recv_decode(s, detail::recv_until_decoder(data, delimiter),
total_bytes_recvd, error_handler);
}
/// Start an asynchronous receive that will not complete until the specified
/// delimiter is encountered.
/**
* This function is used to asynchronously receive data from a stream until a
* given delimiter is found. The function call always returns immediately.
*
* @param s The stream on which the data is to be received.
*
* @param data The std:::string object into which the received data will be
* written. Ownership of the object is retained by the caller, which must
* guarantee that it is valid until the handler is called.
*
* @param delimiter The pattern marking the end of the data to receive. Copies
* will be made of the string as required.
*
* @param handler The handler to be called when the receive operation
* completes. Copies will be made of the handler as required. The equivalent
* function signature of the handler must be:
* @code template <typename Error>
* void handler(
* const Error& error, // Result of operation (the actual type is
* // dependent on the underlying stream's recv
* // operation)
* size_t last_bytes_recvd, // Number of bytes received on last recv
* // operation
* size_t total_bytes_recvd // Total number of bytes successfully received
* ); @endcode
*/
template <typename Buffered_Stream, typename Handler>
inline void async_recv_until(Buffered_Stream& s, std::string& data,
const std::string& delimiter, Handler handler)
{
async_recv_decode(s, detail::recv_until_decoder(data, delimiter), handler);
}
} // namespace asio } // namespace asio
#include "asio/detail/pop_options.hpp" #include "asio/detail/pop_options.hpp"