read_some, async_read_some return bytes used

fix #659
This commit is contained in:
Vinnie Falco
2017-07-16 11:28:59 -07:00
parent 04887c49e0
commit 60e133ab4c
3 changed files with 41 additions and 20 deletions

View File

@ -5,6 +5,7 @@ Version 83:
* Add wstest compression option * Add wstest compression option
* Turn some flat_static_buffer_tests on * Turn some flat_static_buffer_tests on
* Documentation work * Documentation work
* read_some, async_read_some return bytes used
WebSocket WebSocket

View File

@ -41,6 +41,7 @@ class read_some_op
basic_parser<isRequest, Derived>& p_; basic_parser<isRequest, Derived>& p_;
boost::optional<typename boost::optional<typename
DynamicBuffer::mutable_buffers_type> mb_; DynamicBuffer::mutable_buffers_type> mb_;
std::size_t used_ = 0;
Handler h_; Handler h_;
public: public:
@ -136,10 +137,14 @@ operator()(error_code ec, std::size_t bytes_transferred)
b_.commit(bytes_transferred); b_.commit(bytes_transferred);
do_parse: do_parse:
b_.consume(p_.put(b_.data(), ec)); {
auto const used = p_.put(b_.data(), ec);
used_ += used;
b_.consume(used);
if(! ec || ec != http::error::need_more) if(! ec || ec != http::error::need_more)
goto do_upcall; goto do_upcall;
ec.assign(0, ec.category()); ec.assign(0, ec.category());
}
do_read: do_read:
try try
@ -165,7 +170,7 @@ operator()(error_code ec, std::size_t bytes_transferred)
break; break;
} }
upcall: upcall:
h_(ec); h_(ec, used_);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -219,7 +224,8 @@ public:
} }
void void
operator()(error_code ec); operator()(
error_code ec, std::size_t bytes_used = 0);
friend friend
void* asio_handler_allocate( void* asio_handler_allocate(
@ -264,7 +270,7 @@ template<class Stream, class DynamicBuffer,
void void
read_op<Stream, DynamicBuffer, read_op<Stream, DynamicBuffer,
isRequest, Derived, Condition, Handler>:: isRequest, Derived, Condition, Handler>::
operator()(error_code ec) operator()(error_code ec, std::size_t)
{ {
switch(state_) switch(state_)
{ {
@ -343,7 +349,8 @@ public:
} }
void void
operator()(error_code ec); operator()(
error_code ec, std::size_t bytes_used = 0);
friend friend
void* asio_handler_allocate( void* asio_handler_allocate(
@ -388,7 +395,7 @@ template<class Stream, class DynamicBuffer,
void void
read_msg_op<Stream, DynamicBuffer, read_msg_op<Stream, DynamicBuffer,
isRequest, Body, Allocator, Handler>:: isRequest, Body, Allocator, Handler>::
operator()(error_code ec) operator()(error_code ec, std::size_t)
{ {
auto& d = *d_; auto& d = *d_;
switch(d.state) switch(d.state)
@ -424,7 +431,7 @@ template<
class SyncReadStream, class SyncReadStream,
class DynamicBuffer, class DynamicBuffer,
bool isRequest, class Derived> bool isRequest, class Derived>
void std::size_t
read_some( read_some(
SyncReadStream& stream, SyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,
@ -436,16 +443,18 @@ read_some(
"DynamicBuffer requirements not met"); "DynamicBuffer requirements not met");
BOOST_ASSERT(! parser.is_done()); BOOST_ASSERT(! parser.is_done());
error_code ec; error_code ec;
read_some(stream, buffer, parser, ec); auto const bytes_used = read_some(
stream, buffer, parser, ec);
if(ec) if(ec)
BOOST_THROW_EXCEPTION(system_error{ec}); BOOST_THROW_EXCEPTION(system_error{ec});
return bytes_used;
} }
template< template<
class SyncReadStream, class SyncReadStream,
class DynamicBuffer, class DynamicBuffer,
bool isRequest, class Derived> bool isRequest, class Derived>
void std::size_t
read_some( read_some(
SyncReadStream& stream, SyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,
@ -457,16 +466,21 @@ read_some(
static_assert(is_dynamic_buffer<DynamicBuffer>::value, static_assert(is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met"); "DynamicBuffer requirements not met");
BOOST_ASSERT(! parser.is_done()); BOOST_ASSERT(! parser.is_done());
std::size_t bytes_used = 0;
if(buffer.size() == 0) if(buffer.size() == 0)
goto do_read; goto do_read;
for(;;) for(;;)
{ {
// invoke parser // invoke parser
buffer.consume(parser.put(buffer.data(), ec)); {
if(! ec) auto const used = parser.put(buffer.data(), ec);
break; bytes_used += used;
if(ec != http::error::need_more) buffer.consume(used);
break; if(! ec)
break;
if(ec != http::error::need_more)
break;
}
do_read: do_read:
boost::optional<typename boost::optional<typename
DynamicBuffer::mutable_buffers_type> b; DynamicBuffer::mutable_buffers_type> b;
@ -478,7 +492,7 @@ read_some(
catch(std::length_error const&) catch(std::length_error const&)
{ {
ec = error::buffer_overflow; ec = error::buffer_overflow;
return; return bytes_used;
} }
auto const bytes_transferred = auto const bytes_transferred =
stream.read_some(*b, ec); stream.read_some(*b, ec);
@ -501,6 +515,7 @@ read_some(
break; break;
buffer.commit(bytes_transferred); buffer.commit(bytes_transferred);
} }
return bytes_used;
} }
template< template<
@ -509,7 +524,7 @@ template<
bool isRequest, class Derived, bool isRequest, class Derived,
class ReadHandler> class ReadHandler>
async_return_type< async_return_type<
ReadHandler, void(error_code)> ReadHandler, void(error_code, std::size_t)>
async_read_some( async_read_some(
AsyncReadStream& stream, AsyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,

View File

@ -56,13 +56,15 @@ namespace http {
@param parser The parser to use. @param parser The parser to use.
@return The number of bytes consumed by the parser.
@throws system_error Thrown on failure. @throws system_error Thrown on failure.
*/ */
template< template<
class SyncReadStream, class SyncReadStream,
class DynamicBuffer, class DynamicBuffer,
bool isRequest, class Derived> bool isRequest, class Derived>
void std::size_t
read_some( read_some(
SyncReadStream& stream, SyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,
@ -112,12 +114,14 @@ read_some(
@param parser The parser to use. @param parser The parser to use.
@param ec Set to the error, if any occurred. @param ec Set to the error, if any occurred.
@return The number of bytes consumed by the parser.
*/ */
template< template<
class SyncReadStream, class SyncReadStream,
class DynamicBuffer, class DynamicBuffer,
bool isRequest, class Derived> bool isRequest, class Derived>
void std::size_t
read_some( read_some(
SyncReadStream& stream, SyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,
@ -172,7 +176,8 @@ read_some(
completes. Copies will be made of the handler as required. completes. Copies will be made of the handler as required.
The equivalent function signature of the handler must be: The equivalent function signature of the handler must be:
@code void handler( @code void handler(
error_code const& error // result of operation error_code const& error, // result of operation
std::size_t bytes_used // the number of bytes consumed by the parser
); @endcode ); @endcode
Regardless of whether the asynchronous operation completes Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within immediately or not, the handler will not be invoked from within
@ -193,7 +198,7 @@ template<
void_or_deduced void_or_deduced
#else #else
async_return_type< async_return_type<
ReadHandler, void(error_code)> ReadHandler, void(error_code, std::size_t)>
#endif #endif
async_read_some( async_read_some(
AsyncReadStream& stream, AsyncReadStream& stream,