File indexing completed on 2025-01-18 09:29:26
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_BEAST_CORE_IMPL_BUFFERS_GENERATOR_HPP
0011 #define BOOST_BEAST_CORE_IMPL_BUFFERS_GENERATOR_HPP
0012
0013 #include <boost/beast/core/buffers_generator.hpp>
0014
0015 #include <boost/asio/write.hpp>
0016 #include <boost/asio/async_result.hpp>
0017 #include <boost/asio/compose.hpp>
0018 #include <boost/asio/coroutine.hpp>
0019
0020 #include <boost/beast/core/buffer_traits.hpp>
0021 #include <boost/beast/core/stream_traits.hpp>
0022
0023 #include <boost/throw_exception.hpp>
0024 #include <type_traits>
0025
0026 namespace boost {
0027 namespace beast {
0028
0029 namespace detail {
0030
0031 template <
0032 class AsyncWriteStream,
0033 class BuffersGenerator>
0034 struct write_buffers_generator_op
0035 : boost::asio::coroutine
0036 {
0037 write_buffers_generator_op(
0038 AsyncWriteStream& s, BuffersGenerator g)
0039 : s_(s)
0040 , g_(std::move(g))
0041 {
0042 }
0043
0044 template<class Self>
0045 void operator()(
0046 Self& self, error_code ec = {}, std::size_t n = 0)
0047 {
0048 BOOST_ASIO_CORO_REENTER(*this)
0049 {
0050 while(! g_.is_done())
0051 {
0052 BOOST_ASIO_CORO_YIELD
0053 {
0054 auto cb = g_.prepare(ec);
0055 if(ec)
0056 goto complete;
0057 s_.async_write_some(
0058 cb, std::move(self));
0059 }
0060 if(ec)
0061 goto complete;
0062
0063 g_.consume(n);
0064
0065 total_ += n;
0066 }
0067
0068 complete:
0069 self.complete(ec, total_);
0070 }
0071 }
0072
0073 private:
0074 AsyncWriteStream& s_;
0075 BuffersGenerator g_;
0076 std::size_t total_ = 0;
0077 };
0078
0079 }
0080
0081 template<
0082 class SyncWriteStream,
0083 class BuffersGenerator,
0084 typename std::enable_if<
0085 is_buffers_generator<typename std::decay<
0086 BuffersGenerator>::type>::value>::type*
0087 >
0088 size_t
0089 write(
0090 SyncWriteStream& stream,
0091 BuffersGenerator&& generator,
0092 beast::error_code& ec)
0093 {
0094 static_assert(
0095 is_sync_write_stream<SyncWriteStream>::value,
0096 "SyncWriteStream type requirements not met");
0097
0098 ec.clear();
0099 size_t total = 0;
0100 while(! generator.is_done())
0101 {
0102 auto cb = generator.prepare(ec);
0103 if(ec)
0104 break;
0105
0106 size_t n = net::write(stream, cb, ec);
0107
0108 if(ec)
0109 break;
0110
0111 generator.consume(n);
0112 total += n;
0113 }
0114
0115 return total;
0116 }
0117
0118
0119
0120 template<
0121 class SyncWriteStream,
0122 class BuffersGenerator,
0123 typename std::enable_if<is_buffers_generator<
0124 typename std::decay<BuffersGenerator>::type>::value>::
0125 type*
0126 >
0127 std::size_t
0128 write(SyncWriteStream& stream, BuffersGenerator&& generator)
0129 {
0130 static_assert(
0131 is_sync_write_stream<SyncWriteStream>::value,
0132 "SyncWriteStream type requirements not met");
0133 beast::error_code ec;
0134 std::size_t n = write(
0135 stream, std::forward<BuffersGenerator>(generator), ec);
0136 if(ec)
0137 BOOST_THROW_EXCEPTION(system_error{ ec });
0138 return n;
0139 }
0140
0141
0142
0143 template<
0144 class AsyncWriteStream,
0145 class BuffersGenerator,
0146 BOOST_BEAST_ASYNC_TPARAM2 CompletionToken,
0147 typename std::enable_if<is_buffers_generator<
0148 BuffersGenerator>::value>::type*
0149 >
0150 BOOST_BEAST_ASYNC_RESULT2(CompletionToken)
0151 async_write(
0152 AsyncWriteStream& stream,
0153 BuffersGenerator generator,
0154 CompletionToken&& token)
0155 {
0156 static_assert(
0157 beast::is_async_write_stream<AsyncWriteStream>::value,
0158 "AsyncWriteStream type requirements not met");
0159
0160 return net::async_compose<
0161 CompletionToken,
0162 void(error_code, std::size_t)>(
0163 detail::write_buffers_generator_op<
0164 AsyncWriteStream,
0165 BuffersGenerator>{ stream, std::move(generator) },
0166 token,
0167 stream);
0168 }
0169
0170 }
0171 }
0172
0173 #endif