]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // Copyright (c) 2013-2017 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 | ||
8 | #ifndef BEAST_IMPL_DYNABUF_READSTREAM_HPP | |
9 | #define BEAST_IMPL_DYNABUF_READSTREAM_HPP | |
10 | ||
11 | #include <beast/core/bind_handler.hpp> | |
12 | #include <beast/core/error.hpp> | |
13 | #include <beast/core/handler_concepts.hpp> | |
14 | #include <beast/core/handler_helpers.hpp> | |
15 | #include <beast/core/handler_ptr.hpp> | |
16 | ||
17 | namespace beast { | |
18 | ||
19 | template<class Stream, class DynamicBuffer> | |
20 | template<class MutableBufferSequence, class Handler> | |
21 | class dynabuf_readstream< | |
22 | Stream, DynamicBuffer>::read_some_op | |
23 | { | |
24 | // VFALCO What about bool cont for is_continuation? | |
25 | struct data | |
26 | { | |
27 | dynabuf_readstream& srs; | |
28 | MutableBufferSequence bs; | |
29 | int state = 0; | |
30 | ||
31 | data(Handler&, dynabuf_readstream& srs_, | |
32 | MutableBufferSequence const& bs_) | |
33 | : srs(srs_) | |
34 | , bs(bs_) | |
35 | { | |
36 | } | |
37 | }; | |
38 | ||
39 | handler_ptr<data, Handler> d_; | |
40 | ||
41 | public: | |
42 | read_some_op(read_some_op&&) = default; | |
43 | read_some_op(read_some_op const&) = default; | |
44 | ||
45 | template<class DeducedHandler, class... Args> | |
46 | read_some_op(DeducedHandler&& h, | |
47 | dynabuf_readstream& srs, Args&&... args) | |
48 | : d_(std::forward<DeducedHandler>(h), | |
49 | srs, std::forward<Args>(args)...) | |
50 | { | |
51 | (*this)(error_code{}, 0); | |
52 | } | |
53 | ||
54 | void | |
55 | operator()(error_code const& ec, | |
56 | std::size_t bytes_transferred); | |
57 | ||
58 | friend | |
59 | void* asio_handler_allocate( | |
60 | std::size_t size, read_some_op* op) | |
61 | { | |
62 | return beast_asio_helpers:: | |
63 | allocate(size, op->d_.handler()); | |
64 | } | |
65 | ||
66 | friend | |
67 | void asio_handler_deallocate( | |
68 | void* p, std::size_t size, read_some_op* op) | |
69 | { | |
70 | return beast_asio_helpers:: | |
71 | deallocate(p, size, op->d_.handler()); | |
72 | } | |
73 | ||
74 | friend | |
75 | bool asio_handler_is_continuation(read_some_op* op) | |
76 | { | |
77 | return beast_asio_helpers:: | |
78 | is_continuation(op->d_.handler()); | |
79 | } | |
80 | ||
81 | template<class Function> | |
82 | friend | |
83 | void asio_handler_invoke(Function&& f, read_some_op* op) | |
84 | { | |
85 | return beast_asio_helpers:: | |
86 | invoke(f, op->d_.handler()); | |
87 | } | |
88 | }; | |
89 | ||
90 | template<class Stream, class DynamicBuffer> | |
91 | template<class MutableBufferSequence, class Handler> | |
92 | void | |
93 | dynabuf_readstream<Stream, DynamicBuffer>:: | |
94 | read_some_op<MutableBufferSequence, Handler>::operator()( | |
95 | error_code const& ec, std::size_t bytes_transferred) | |
96 | { | |
97 | auto& d = *d_; | |
98 | while(! ec && d.state != 99) | |
99 | { | |
100 | switch(d.state) | |
101 | { | |
102 | case 0: | |
103 | if(d.srs.sb_.size() == 0) | |
104 | { | |
105 | d.state = | |
106 | d.srs.capacity_ > 0 ? 2 : 1; | |
107 | break; | |
108 | } | |
109 | d.state = 4; | |
110 | d.srs.get_io_service().post( | |
111 | bind_handler(std::move(*this), ec, 0)); | |
112 | return; | |
113 | ||
114 | case 1: | |
115 | // read (unbuffered) | |
116 | d.state = 99; | |
117 | d.srs.next_layer_.async_read_some( | |
118 | d.bs, std::move(*this)); | |
119 | return; | |
120 | ||
121 | case 2: | |
122 | // read | |
123 | d.state = 3; | |
124 | d.srs.next_layer_.async_read_some( | |
125 | d.srs.sb_.prepare(d.srs.capacity_), | |
126 | std::move(*this)); | |
127 | return; | |
128 | ||
129 | // got data | |
130 | case 3: | |
131 | d.state = 4; | |
132 | d.srs.sb_.commit(bytes_transferred); | |
133 | break; | |
134 | ||
135 | // copy | |
136 | case 4: | |
137 | bytes_transferred = | |
138 | boost::asio::buffer_copy( | |
139 | d.bs, d.srs.sb_.data()); | |
140 | d.srs.sb_.consume(bytes_transferred); | |
141 | // call handler | |
142 | d.state = 99; | |
143 | break; | |
144 | } | |
145 | } | |
146 | d_.invoke(ec, bytes_transferred); | |
147 | } | |
148 | ||
149 | //------------------------------------------------------------------------------ | |
150 | ||
151 | template<class Stream, class DynamicBuffer> | |
152 | template<class... Args> | |
153 | dynabuf_readstream<Stream, DynamicBuffer>:: | |
154 | dynabuf_readstream(Args&&... args) | |
155 | : next_layer_(std::forward<Args>(args)...) | |
156 | { | |
157 | } | |
158 | ||
159 | template<class Stream, class DynamicBuffer> | |
160 | template<class ConstBufferSequence, class WriteHandler> | |
161 | auto | |
162 | dynabuf_readstream<Stream, DynamicBuffer>:: | |
163 | async_write_some(ConstBufferSequence const& buffers, | |
164 | WriteHandler&& handler) -> | |
165 | typename async_completion< | |
166 | WriteHandler, void(error_code)>::result_type | |
167 | { | |
168 | static_assert(is_AsyncWriteStream<next_layer_type>::value, | |
169 | "AsyncWriteStream requirements not met"); | |
170 | static_assert(is_ConstBufferSequence< | |
171 | ConstBufferSequence>::value, | |
172 | "ConstBufferSequence requirements not met"); | |
173 | static_assert(is_CompletionHandler<WriteHandler, | |
174 | void(error_code, std::size_t)>::value, | |
175 | "WriteHandler requirements not met"); | |
176 | return next_layer_.async_write_some(buffers, | |
177 | std::forward<WriteHandler>(handler)); | |
178 | } | |
179 | ||
180 | template<class Stream, class DynamicBuffer> | |
181 | template<class MutableBufferSequence> | |
182 | std::size_t | |
183 | dynabuf_readstream<Stream, DynamicBuffer>:: | |
184 | read_some( | |
185 | MutableBufferSequence const& buffers) | |
186 | { | |
187 | static_assert(is_SyncReadStream<next_layer_type>::value, | |
188 | "SyncReadStream requirements not met"); | |
189 | static_assert(is_MutableBufferSequence< | |
190 | MutableBufferSequence>::value, | |
191 | "MutableBufferSequence requirements not met"); | |
192 | error_code ec; | |
193 | auto n = read_some(buffers, ec); | |
194 | if(ec) | |
195 | throw system_error{ec}; | |
196 | return n; | |
197 | } | |
198 | ||
199 | template<class Stream, class DynamicBuffer> | |
200 | template<class MutableBufferSequence> | |
201 | std::size_t | |
202 | dynabuf_readstream<Stream, DynamicBuffer>:: | |
203 | read_some(MutableBufferSequence const& buffers, | |
204 | error_code& ec) | |
205 | { | |
206 | static_assert(is_SyncReadStream<next_layer_type>::value, | |
207 | "SyncReadStream requirements not met"); | |
208 | static_assert(is_MutableBufferSequence< | |
209 | MutableBufferSequence>::value, | |
210 | "MutableBufferSequence requirements not met"); | |
211 | using boost::asio::buffer_size; | |
212 | using boost::asio::buffer_copy; | |
213 | if(sb_.size() == 0) | |
214 | { | |
215 | if(capacity_ == 0) | |
216 | return next_layer_.read_some(buffers, ec); | |
217 | sb_.commit(next_layer_.read_some( | |
218 | sb_.prepare(capacity_), ec)); | |
219 | if(ec) | |
220 | return 0; | |
221 | } | |
222 | auto bytes_transferred = | |
223 | buffer_copy(buffers, sb_.data()); | |
224 | sb_.consume(bytes_transferred); | |
225 | return bytes_transferred; | |
226 | } | |
227 | ||
228 | template<class Stream, class DynamicBuffer> | |
229 | template<class MutableBufferSequence, class ReadHandler> | |
230 | auto | |
231 | dynabuf_readstream<Stream, DynamicBuffer>:: | |
232 | async_read_some( | |
233 | MutableBufferSequence const& buffers, | |
234 | ReadHandler&& handler) -> | |
235 | typename async_completion< | |
236 | ReadHandler, void(error_code)>::result_type | |
237 | { | |
238 | static_assert(is_AsyncReadStream<next_layer_type>::value, | |
239 | "Stream requirements not met"); | |
240 | static_assert(is_MutableBufferSequence< | |
241 | MutableBufferSequence>::value, | |
242 | "MutableBufferSequence requirements not met"); | |
243 | beast::async_completion< | |
244 | ReadHandler, void(error_code, std::size_t) | |
245 | > completion{handler}; | |
246 | read_some_op<MutableBufferSequence, | |
247 | decltype(completion.handler)>{ | |
248 | completion.handler, *this, buffers}; | |
249 | return completion.result.get(); | |
250 | } | |
251 | ||
252 | } // beast | |
253 | ||
254 | #endif |