File indexing completed on 2025-12-16 09:43:54
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_BEAST_DETAIL_IMPL_READ_HPP
0011 #define BOOST_BEAST_DETAIL_IMPL_READ_HPP
0012
0013 #include <boost/beast/core/async_base.hpp>
0014 #include <boost/beast/core/flat_static_buffer.hpp>
0015 #include <boost/beast/core/read_size.hpp>
0016 #include <boost/asio/basic_stream_socket.hpp>
0017 #include <boost/asio/coroutine.hpp>
0018 #include <boost/throw_exception.hpp>
0019
0020 namespace boost {
0021 namespace beast {
0022 namespace detail {
0023
0024
0025 static std::size_t constexpr default_max_stack_buffer = 16384;
0026
0027
0028
0029 struct dynamic_read_ops
0030 {
0031
0032
0033
0034 template<
0035 class Stream,
0036 class DynamicBuffer,
0037 class Condition,
0038 class Handler>
0039 class read_op
0040 : public asio::coroutine
0041 , public async_base<
0042 Handler, beast::executor_type<Stream>>
0043 {
0044 Stream& s_;
0045 DynamicBuffer& b_;
0046 Condition cond_;
0047 error_code ec_;
0048 std::size_t total_ = 0;
0049
0050 public:
0051 read_op(read_op&&) = default;
0052
0053 template<class Handler_, class Condition_>
0054 read_op(
0055 Handler_&& h,
0056 Stream& s,
0057 DynamicBuffer& b,
0058 Condition_&& cond)
0059 : async_base<Handler,
0060 beast::executor_type<Stream>>(
0061 std::forward<Handler_>(h),
0062 s.get_executor())
0063 , s_(s)
0064 , b_(b)
0065 , cond_(std::forward<Condition_>(cond))
0066 {
0067 (*this)({}, 0, false);
0068 }
0069
0070 void
0071 operator()(
0072 error_code ec,
0073 std::size_t bytes_transferred,
0074 bool cont = true)
0075 {
0076 std::size_t max_prepare;
0077 BOOST_ASIO_CORO_REENTER(*this)
0078 {
0079 for(;;)
0080 {
0081 max_prepare = beast::read_size(b_, cond_(ec, total_, b_));
0082 if(max_prepare == 0)
0083 break;
0084 BOOST_ASIO_CORO_YIELD
0085 s_.async_read_some(
0086 b_.prepare(max_prepare), std::move(*this));
0087 b_.commit(bytes_transferred);
0088 total_ += bytes_transferred;
0089 }
0090 if(! cont)
0091 {
0092
0093
0094 ec_ = ec;
0095 BOOST_ASIO_CORO_YIELD
0096 s_.async_read_some(
0097 b_.prepare(0), std::move(*this));
0098 BOOST_BEAST_ASSIGN_EC(ec, ec_);
0099 }
0100 this->complete_now(ec, total_);
0101 }
0102 }
0103 };
0104
0105
0106
0107 template <typename AsyncReadStream>
0108 struct run_read_op
0109 {
0110 AsyncReadStream* stream;
0111
0112 using executor_type = typename AsyncReadStream::executor_type;
0113
0114 executor_type
0115 get_executor() const noexcept
0116 {
0117 return stream->get_executor();
0118 }
0119
0120 template<
0121 class DynamicBuffer,
0122 class Condition,
0123 class ReadHandler>
0124 void
0125 operator()(
0126 ReadHandler&& h,
0127 DynamicBuffer* b,
0128 Condition&& c)
0129 {
0130
0131
0132
0133
0134 static_assert(
0135 beast::detail::is_invocable<ReadHandler,
0136 void(error_code, std::size_t)>::value,
0137 "ReadHandler type requirements not met");
0138
0139 read_op<
0140 AsyncReadStream,
0141 DynamicBuffer,
0142 typename std::decay<Condition>::type,
0143 typename std::decay<ReadHandler>::type>(
0144 std::forward<ReadHandler>(h),
0145 *stream,
0146 *b,
0147 std::forward<Condition>(c));
0148 }
0149
0150 };
0151
0152 };
0153
0154
0155
0156 template<
0157 class SyncReadStream,
0158 class DynamicBuffer,
0159 class CompletionCondition,
0160 class>
0161 std::size_t
0162 read(
0163 SyncReadStream& stream,
0164 DynamicBuffer& buffer,
0165 CompletionCondition cond)
0166 {
0167 static_assert(is_sync_read_stream<SyncReadStream>::value,
0168 "SyncReadStream type requirements not met");
0169 static_assert(
0170 net::is_dynamic_buffer<DynamicBuffer>::value,
0171 "DynamicBuffer type requirements not met");
0172 static_assert(
0173 detail::is_invocable<CompletionCondition,
0174 void(error_code&, std::size_t, DynamicBuffer&)>::value,
0175 "CompletionCondition type requirements not met");
0176 error_code ec;
0177 auto const bytes_transferred = detail::read(
0178 stream, buffer, std::move(cond), ec);
0179 if(ec)
0180 BOOST_THROW_EXCEPTION(system_error{ec});
0181 return bytes_transferred;
0182 }
0183
0184 template<
0185 class SyncReadStream,
0186 class DynamicBuffer,
0187 class CompletionCondition,
0188 class>
0189 std::size_t
0190 read(
0191 SyncReadStream& stream,
0192 DynamicBuffer& buffer,
0193 CompletionCondition cond,
0194 error_code& ec)
0195 {
0196 static_assert(is_sync_read_stream<SyncReadStream>::value,
0197 "SyncReadStream type requirements not met");
0198 static_assert(
0199 net::is_dynamic_buffer<DynamicBuffer>::value,
0200 "DynamicBuffer type requirements not met");
0201 static_assert(
0202 detail::is_invocable<CompletionCondition,
0203 void(error_code&, std::size_t, DynamicBuffer&)>::value,
0204 "CompletionCondition type requirements not met");
0205 ec = {};
0206 std::size_t total = 0;
0207 std::size_t max_prepare;
0208 for(;;)
0209 {
0210 max_prepare = beast::read_size(buffer, cond(ec, total, buffer));
0211 if(max_prepare == 0)
0212 break;
0213 std::size_t const bytes_transferred =
0214 stream.read_some(buffer.prepare(max_prepare), ec);
0215 buffer.commit(bytes_transferred);
0216 total += bytes_transferred;
0217 }
0218 return total;
0219 }
0220
0221 template<
0222 class AsyncReadStream,
0223 class DynamicBuffer,
0224 class CompletionCondition,
0225 BOOST_BEAST_ASYNC_TPARAM2 ReadHandler,
0226 class>
0227 BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
0228 async_read(
0229 AsyncReadStream& stream,
0230 DynamicBuffer& buffer,
0231 CompletionCondition&& cond,
0232 ReadHandler&& handler)
0233 {
0234 static_assert(is_async_read_stream<AsyncReadStream>::value,
0235 "AsyncReadStream type requirements not met");
0236 static_assert(
0237 net::is_dynamic_buffer<DynamicBuffer>::value,
0238 "DynamicBuffer type requirements not met");
0239 static_assert(
0240 detail::is_invocable<CompletionCondition,
0241 void(error_code&, std::size_t, DynamicBuffer&)>::value,
0242 "CompletionCondition type requirements not met");
0243 return net::async_initiate<
0244 ReadHandler,
0245 void(error_code, std::size_t)>(
0246 typename dynamic_read_ops::run_read_op<AsyncReadStream>{&stream},
0247 handler,
0248 &buffer,
0249 std::forward<CompletionCondition>(cond));
0250 }
0251
0252 }
0253 }
0254 }
0255
0256 #endif