1//
2// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3//
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7// Official repository: https://github.com/boostorg/beast
8//
9
10#ifndef BOOST_BEAST_IMPL_BUFFERED_READ_STREAM_HPP
11#define BOOST_BEAST_IMPL_BUFFERED_READ_STREAM_HPP
12
13#include <boost/beast/core/async_base.hpp>
14#include <boost/beast/core/error.hpp>
15#include <boost/beast/core/read_size.hpp>
16#include <boost/beast/core/stream_traits.hpp>
17#include <boost/beast/core/detail/is_invocable.hpp>
18#include <boost/asio/dispatch.hpp>
19#include <boost/asio/prepend.hpp>
20#include <boost/throw_exception.hpp>
21
22namespace boost {
23namespace beast {
24
25
26template<class Stream, class DynamicBuffer>
27struct buffered_read_stream<Stream, DynamicBuffer>::ops
28{
29
30template<class MutableBufferSequence, class Handler>
31class read_op
32 : public async_base<Handler,
33 beast::executor_type<buffered_read_stream>>
34{
35 buffered_read_stream& s_;
36 MutableBufferSequence b_;
37 int step_ = 0;
38
39public:
40 read_op(read_op&&) = default;
41 read_op(read_op const&) = delete;
42
43 template<class Handler_>
44 read_op(
45 Handler_&& h,
46 buffered_read_stream& s,
47 MutableBufferSequence const& b)
48 : async_base<
49 Handler, beast::executor_type<buffered_read_stream>>(
50 std::forward<Handler_>(h), s.get_executor())
51 , s_(s)
52 , b_(b)
53 {
54 (*this)({}, 0);
55 }
56
57 void
58 operator()(
59 error_code ec,
60 std::size_t bytes_transferred)
61 {
62 // VFALCO TODO Rewrite this using reenter/yield
63 switch(step_)
64 {
65 case 0:
66 if(s_.buffer_.size() == 0)
67 {
68 if(s_.capacity_ == 0)
69 {
70 // read (unbuffered)
71 step_ = 1;
72 return s_.next_layer_.async_read_some(
73 b_, std::move(*this));
74 }
75 // read
76 step_ = 2;
77 return s_.next_layer_.async_read_some(
78 s_.buffer_.prepare(read_size(
79 s_.buffer_, s_.capacity_)),
80 std::move(*this));
81 }
82 step_ = 3;
83 {
84 const auto ex = this->get_immediate_executor();
85 return net::dispatch(
86 ex,
87 net::prepend(std::move(*this), ec, 0));
88 }
89 case 1:
90 // upcall
91 break;
92
93 case 2:
94 s_.buffer_.commit(bytes_transferred);
95 BOOST_FALLTHROUGH;
96
97 case 3:
98 bytes_transferred =
99 net::buffer_copy(b_, s_.buffer_.data());
100 s_.buffer_.consume(bytes_transferred);
101 break;
102 }
103 this->complete_now(ec, bytes_transferred);
104 }
105};
106
107struct run_read_op
108{
109 template<class ReadHandler, class Buffers>
110 void
111 operator()(
112 ReadHandler&& h,
113 buffered_read_stream* s,
114 Buffers const* b)
115 {
116 // If you get an error on the following line it means
117 // that your handler does not meet the documented type
118 // requirements for the handler.
119
120 static_assert(
121 beast::detail::is_invocable<ReadHandler,
122 void(error_code, std::size_t)>::value,
123 "ReadHandler type requirements not met");
124
125 read_op<
126 Buffers,
127 typename std::decay<ReadHandler>::type>(
128 std::forward<ReadHandler>(h), *s, *b);
129 }
130};
131
132};
133
134//------------------------------------------------------------------------------
135
136template<class Stream, class DynamicBuffer>
137template<class... Args>
138buffered_read_stream<Stream, DynamicBuffer>::
139buffered_read_stream(Args&&... args)
140 : next_layer_(std::forward<Args>(args)...)
141{
142}
143
144template<class Stream, class DynamicBuffer>
145template<class ConstBufferSequence, BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
146BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
147buffered_read_stream<Stream, DynamicBuffer>::
148async_write_some(
149 ConstBufferSequence const& buffers,
150 WriteHandler&& handler)
151{
152 static_assert(is_async_write_stream<next_layer_type>::value,
153 "AsyncWriteStream type requirements not met");
154 static_assert(net::is_const_buffer_sequence<
155 ConstBufferSequence>::value,
156 "ConstBufferSequence type requirements not met");
157 static_assert(detail::is_completion_token_for<WriteHandler,
158 void(error_code, std::size_t)>::value,
159 "WriteHandler type requirements not met");
160 return next_layer_.async_write_some(buffers,
161 std::forward<WriteHandler>(handler));
162}
163
164template<class Stream, class DynamicBuffer>
165template<class MutableBufferSequence>
166std::size_t
167buffered_read_stream<Stream, DynamicBuffer>::
168read_some(
169 MutableBufferSequence const& buffers)
170{
171 static_assert(is_sync_read_stream<next_layer_type>::value,
172 "SyncReadStream type requirements not met");
173 static_assert(net::is_mutable_buffer_sequence<
174 MutableBufferSequence>::value,
175 "MutableBufferSequence type requirements not met");
176 error_code ec;
177 auto n = read_some(buffers, ec);
178 if(ec)
179 BOOST_THROW_EXCEPTION(system_error{ec});
180 return n;
181}
182
183template<class Stream, class DynamicBuffer>
184template<class MutableBufferSequence>
185std::size_t
186buffered_read_stream<Stream, DynamicBuffer>::
187read_some(MutableBufferSequence const& buffers,
188 error_code& ec)
189{
190 static_assert(is_sync_read_stream<next_layer_type>::value,
191 "SyncReadStream type requirements not met");
192 static_assert(net::is_mutable_buffer_sequence<
193 MutableBufferSequence>::value,
194 "MutableBufferSequence type requirements not met");
195 if(buffer_.size() == 0)
196 {
197 if(capacity_ == 0)
198 return next_layer_.read_some(buffers, ec);
199 buffer_.commit(next_layer_.read_some(
200 buffer_.prepare(read_size(buffer_,
201 capacity_)), ec));
202 if(ec)
203 return 0;
204 }
205 else
206 {
207 ec = {};
208 }
209 auto bytes_transferred =
210 net::buffer_copy(buffers, buffer_.data());
211 buffer_.consume(bytes_transferred);
212 return bytes_transferred;
213}
214
215template<class Stream, class DynamicBuffer>
216template<class MutableBufferSequence, BOOST_BEAST_ASYNC_TPARAM2 ReadHandler>
217BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
218buffered_read_stream<Stream, DynamicBuffer>::
219async_read_some(
220 MutableBufferSequence const& buffers,
221 ReadHandler&& handler)
222{
223 static_assert(is_async_read_stream<next_layer_type>::value,
224 "AsyncReadStream type requirements not met");
225 static_assert(net::is_mutable_buffer_sequence<
226 MutableBufferSequence>::value,
227 "MutableBufferSequence type requirements not met");
228 if(buffer_.size() == 0 && capacity_ == 0)
229 return next_layer_.async_read_some(buffers,
230 std::forward<ReadHandler>(handler));
231 return net::async_initiate<
232 ReadHandler,
233 void(error_code, std::size_t)>(
234 typename ops::run_read_op{},
235 handler,
236 this,
237 &buffers);
238}
239
240} // beast
241} // boost
242
243#endif
244

source code of boost/libs/beast/include/boost/beast/core/impl/buffered_read_stream.hpp