%PDF- %PDF-
Direktori : /backups/router/usr/local/include/boost/beast/core/detail/impl/ |
Current File : //backups/router/usr/local/include/boost/beast/core/detail/impl/read.hpp |
// // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail 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) // // Official repository: https://github.com/boostorg/beast // #ifndef BOOST_BEAST_DETAIL_IMPL_READ_HPP #define BOOST_BEAST_DETAIL_IMPL_READ_HPP #include <boost/beast/core/async_base.hpp> #include <boost/beast/core/flat_static_buffer.hpp> #include <boost/beast/core/read_size.hpp> #include <boost/asio/basic_stream_socket.hpp> #include <boost/asio/coroutine.hpp> #include <boost/throw_exception.hpp> namespace boost { namespace beast { namespace detail { // The number of bytes in the stack buffer when using non-blocking. static std::size_t constexpr default_max_stack_buffer = 16384; //------------------------------------------------------------------------------ struct dynamic_read_ops { // read into a dynamic buffer until the // condition is met or an error occurs template< class Stream, class DynamicBuffer, class Condition, class Handler> class read_op : public asio::coroutine , public async_base< Handler, beast::executor_type<Stream>> { Stream& s_; DynamicBuffer& b_; Condition cond_; error_code ec_; std::size_t total_ = 0; public: read_op(read_op&&) = default; template<class Handler_, class Condition_> read_op( Handler_&& h, Stream& s, DynamicBuffer& b, Condition_&& cond) : async_base<Handler, beast::executor_type<Stream>>( std::forward<Handler_>(h), s.get_executor()) , s_(s) , b_(b) , cond_(std::forward<Condition_>(cond)) { (*this)({}, 0, false); } void operator()( error_code ec, std::size_t bytes_transferred, bool cont = true) { std::size_t max_prepare; BOOST_ASIO_CORO_REENTER(*this) { for(;;) { max_prepare = beast::read_size(b_, cond_(ec, total_, b_)); if(max_prepare == 0) break; BOOST_ASIO_CORO_YIELD s_.async_read_some( b_.prepare(max_prepare), std::move(*this)); b_.commit(bytes_transferred); total_ += bytes_transferred; } if(! cont) { // run this handler "as-if" using net::post // to reduce template instantiations ec_ = ec; BOOST_ASIO_CORO_YIELD s_.async_read_some( b_.prepare(0), std::move(*this)); BOOST_BEAST_ASSIGN_EC(ec, ec_); } this->complete_now(ec, total_); } } }; //------------------------------------------------------------------------------ template <typename AsyncReadStream> struct run_read_op { AsyncReadStream* stream; using executor_type = typename AsyncReadStream::executor_type; executor_type get_executor() const noexcept { return stream->get_executor(); } template< class DynamicBuffer, class Condition, class ReadHandler> void operator()( ReadHandler&& h, DynamicBuffer* b, Condition&& c) { // If you get an error on the following line it means // that your handler does not meet the documented type // requirements for the handler. static_assert( beast::detail::is_invocable<ReadHandler, void(error_code, std::size_t)>::value, "ReadHandler type requirements not met"); read_op< AsyncReadStream, DynamicBuffer, typename std::decay<Condition>::type, typename std::decay<ReadHandler>::type>( std::forward<ReadHandler>(h), *stream, *b, std::forward<Condition>(c)); } }; }; //------------------------------------------------------------------------------ template< class SyncReadStream, class DynamicBuffer, class CompletionCondition, class> std::size_t read( SyncReadStream& stream, DynamicBuffer& buffer, CompletionCondition cond) { static_assert(is_sync_read_stream<SyncReadStream>::value, "SyncReadStream type requirements not met"); static_assert( net::is_dynamic_buffer<DynamicBuffer>::value, "DynamicBuffer type requirements not met"); static_assert( detail::is_invocable<CompletionCondition, void(error_code&, std::size_t, DynamicBuffer&)>::value, "CompletionCondition type requirements not met"); error_code ec; auto const bytes_transferred = detail::read( stream, buffer, std::move(cond), ec); if(ec) BOOST_THROW_EXCEPTION(system_error{ec}); return bytes_transferred; } template< class SyncReadStream, class DynamicBuffer, class CompletionCondition, class> std::size_t read( SyncReadStream& stream, DynamicBuffer& buffer, CompletionCondition cond, error_code& ec) { static_assert(is_sync_read_stream<SyncReadStream>::value, "SyncReadStream type requirements not met"); static_assert( net::is_dynamic_buffer<DynamicBuffer>::value, "DynamicBuffer type requirements not met"); static_assert( detail::is_invocable<CompletionCondition, void(error_code&, std::size_t, DynamicBuffer&)>::value, "CompletionCondition type requirements not met"); ec = {}; std::size_t total = 0; std::size_t max_prepare; for(;;) { max_prepare = beast::read_size(buffer, cond(ec, total, buffer)); if(max_prepare == 0) break; std::size_t const bytes_transferred = stream.read_some(buffer.prepare(max_prepare), ec); buffer.commit(bytes_transferred); total += bytes_transferred; } return total; } template< class AsyncReadStream, class DynamicBuffer, class CompletionCondition, BOOST_BEAST_ASYNC_TPARAM2 ReadHandler, class> BOOST_BEAST_ASYNC_RESULT2(ReadHandler) async_read( AsyncReadStream& stream, DynamicBuffer& buffer, CompletionCondition&& cond, ReadHandler&& handler) { static_assert(is_async_read_stream<AsyncReadStream>::value, "AsyncReadStream type requirements not met"); static_assert( net::is_dynamic_buffer<DynamicBuffer>::value, "DynamicBuffer type requirements not met"); static_assert( detail::is_invocable<CompletionCondition, void(error_code&, std::size_t, DynamicBuffer&)>::value, "CompletionCondition type requirements not met"); return net::async_initiate< ReadHandler, void(error_code, std::size_t)>( typename dynamic_read_ops::run_read_op<AsyncReadStream>{&stream}, handler, &buffer, std::forward<CompletionCondition>(cond)); } } // detail } // beast } // boost #endif