]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // impl/read_at.hpp | |
3 | // ~~~~~~~~~~~~~~~~ | |
4 | // | |
1e59de90 | 5 | // Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
7c673cae FG |
6 | // |
7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 | // | |
10 | ||
11 | #ifndef BOOST_ASIO_IMPL_READ_AT_HPP | |
12 | #define BOOST_ASIO_IMPL_READ_AT_HPP | |
13 | ||
14 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) | |
15 | # pragma once | |
16 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) | |
17 | ||
18 | #include <algorithm> | |
1e59de90 | 19 | #include <boost/asio/associator.hpp> |
7c673cae FG |
20 | #include <boost/asio/buffer.hpp> |
21 | #include <boost/asio/completion_condition.hpp> | |
22 | #include <boost/asio/detail/array_fwd.hpp> | |
1e59de90 | 23 | #include <boost/asio/detail/base_from_cancellation_state.hpp> |
7c673cae FG |
24 | #include <boost/asio/detail/base_from_completion_cond.hpp> |
25 | #include <boost/asio/detail/bind_handler.hpp> | |
26 | #include <boost/asio/detail/consuming_buffers.hpp> | |
27 | #include <boost/asio/detail/dependent_type.hpp> | |
28 | #include <boost/asio/detail/handler_alloc_helpers.hpp> | |
29 | #include <boost/asio/detail/handler_cont_helpers.hpp> | |
30 | #include <boost/asio/detail/handler_invoke_helpers.hpp> | |
20effc67 | 31 | #include <boost/asio/detail/handler_tracking.hpp> |
7c673cae | 32 | #include <boost/asio/detail/handler_type_requirements.hpp> |
92f5a8d4 | 33 | #include <boost/asio/detail/non_const_lvalue.hpp> |
7c673cae FG |
34 | #include <boost/asio/detail/throw_error.hpp> |
35 | #include <boost/asio/error.hpp> | |
36 | ||
37 | #include <boost/asio/detail/push_options.hpp> | |
38 | ||
39 | namespace boost { | |
40 | namespace asio { | |
41 | ||
b32b8144 FG |
42 | namespace detail |
43 | { | |
44 | template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence, | |
45 | typename MutableBufferIterator, typename CompletionCondition> | |
46 | std::size_t read_at_buffer_sequence(SyncRandomAccessReadDevice& d, | |
47 | uint64_t offset, const MutableBufferSequence& buffers, | |
48 | const MutableBufferIterator&, CompletionCondition completion_condition, | |
49 | boost::system::error_code& ec) | |
50 | { | |
51 | ec = boost::system::error_code(); | |
52 | boost::asio::detail::consuming_buffers<mutable_buffer, | |
53 | MutableBufferSequence, MutableBufferIterator> tmp(buffers); | |
54 | while (!tmp.empty()) | |
55 | { | |
56 | if (std::size_t max_size = detail::adapt_completion_condition_result( | |
57 | completion_condition(ec, tmp.total_consumed()))) | |
58 | { | |
59 | tmp.consume(d.read_some_at(offset + tmp.total_consumed(), | |
60 | tmp.prepare(max_size), ec)); | |
61 | } | |
62 | else | |
63 | break; | |
64 | } | |
20effc67 | 65 | return tmp.total_consumed(); |
b32b8144 FG |
66 | } |
67 | } // namespace detail | |
68 | ||
7c673cae FG |
69 | template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence, |
70 | typename CompletionCondition> | |
71 | std::size_t read_at(SyncRandomAccessReadDevice& d, | |
72 | uint64_t offset, const MutableBufferSequence& buffers, | |
73 | CompletionCondition completion_condition, boost::system::error_code& ec) | |
74 | { | |
b32b8144 | 75 | return detail::read_at_buffer_sequence(d, offset, buffers, |
92f5a8d4 TL |
76 | boost::asio::buffer_sequence_begin(buffers), |
77 | BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); | |
7c673cae FG |
78 | } |
79 | ||
80 | template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence> | |
81 | inline std::size_t read_at(SyncRandomAccessReadDevice& d, | |
82 | uint64_t offset, const MutableBufferSequence& buffers) | |
83 | { | |
84 | boost::system::error_code ec; | |
85 | std::size_t bytes_transferred = read_at( | |
86 | d, offset, buffers, transfer_all(), ec); | |
87 | boost::asio::detail::throw_error(ec, "read_at"); | |
88 | return bytes_transferred; | |
89 | } | |
90 | ||
91 | template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence> | |
92 | inline std::size_t read_at(SyncRandomAccessReadDevice& d, | |
93 | uint64_t offset, const MutableBufferSequence& buffers, | |
94 | boost::system::error_code& ec) | |
95 | { | |
96 | return read_at(d, offset, buffers, transfer_all(), ec); | |
97 | } | |
98 | ||
99 | template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence, | |
100 | typename CompletionCondition> | |
101 | inline std::size_t read_at(SyncRandomAccessReadDevice& d, | |
102 | uint64_t offset, const MutableBufferSequence& buffers, | |
103 | CompletionCondition completion_condition) | |
104 | { | |
105 | boost::system::error_code ec; | |
92f5a8d4 TL |
106 | std::size_t bytes_transferred = read_at(d, offset, buffers, |
107 | BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); | |
7c673cae FG |
108 | boost::asio::detail::throw_error(ec, "read_at"); |
109 | return bytes_transferred; | |
110 | } | |
111 | ||
b32b8144 | 112 | #if !defined(BOOST_ASIO_NO_EXTENSIONS) |
7c673cae FG |
113 | #if !defined(BOOST_ASIO_NO_IOSTREAM) |
114 | ||
115 | template <typename SyncRandomAccessReadDevice, typename Allocator, | |
116 | typename CompletionCondition> | |
117 | std::size_t read_at(SyncRandomAccessReadDevice& d, | |
118 | uint64_t offset, boost::asio::basic_streambuf<Allocator>& b, | |
119 | CompletionCondition completion_condition, boost::system::error_code& ec) | |
120 | { | |
121 | ec = boost::system::error_code(); | |
122 | std::size_t total_transferred = 0; | |
123 | std::size_t max_size = detail::adapt_completion_condition_result( | |
124 | completion_condition(ec, total_transferred)); | |
125 | std::size_t bytes_available = read_size_helper(b, max_size); | |
126 | while (bytes_available > 0) | |
127 | { | |
128 | std::size_t bytes_transferred = d.read_some_at( | |
129 | offset + total_transferred, b.prepare(bytes_available), ec); | |
130 | b.commit(bytes_transferred); | |
131 | total_transferred += bytes_transferred; | |
132 | max_size = detail::adapt_completion_condition_result( | |
133 | completion_condition(ec, total_transferred)); | |
134 | bytes_available = read_size_helper(b, max_size); | |
135 | } | |
136 | return total_transferred; | |
137 | } | |
138 | ||
139 | template <typename SyncRandomAccessReadDevice, typename Allocator> | |
140 | inline std::size_t read_at(SyncRandomAccessReadDevice& d, | |
141 | uint64_t offset, boost::asio::basic_streambuf<Allocator>& b) | |
142 | { | |
143 | boost::system::error_code ec; | |
144 | std::size_t bytes_transferred = read_at( | |
145 | d, offset, b, transfer_all(), ec); | |
146 | boost::asio::detail::throw_error(ec, "read_at"); | |
147 | return bytes_transferred; | |
148 | } | |
149 | ||
150 | template <typename SyncRandomAccessReadDevice, typename Allocator> | |
151 | inline std::size_t read_at(SyncRandomAccessReadDevice& d, | |
152 | uint64_t offset, boost::asio::basic_streambuf<Allocator>& b, | |
153 | boost::system::error_code& ec) | |
154 | { | |
155 | return read_at(d, offset, b, transfer_all(), ec); | |
156 | } | |
157 | ||
158 | template <typename SyncRandomAccessReadDevice, typename Allocator, | |
159 | typename CompletionCondition> | |
160 | inline std::size_t read_at(SyncRandomAccessReadDevice& d, | |
161 | uint64_t offset, boost::asio::basic_streambuf<Allocator>& b, | |
162 | CompletionCondition completion_condition) | |
163 | { | |
164 | boost::system::error_code ec; | |
92f5a8d4 TL |
165 | std::size_t bytes_transferred = read_at(d, offset, b, |
166 | BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); | |
7c673cae FG |
167 | boost::asio::detail::throw_error(ec, "read_at"); |
168 | return bytes_transferred; | |
169 | } | |
170 | ||
171 | #endif // !defined(BOOST_ASIO_NO_IOSTREAM) | |
b32b8144 | 172 | #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) |
7c673cae FG |
173 | |
174 | namespace detail | |
175 | { | |
176 | template <typename AsyncRandomAccessReadDevice, | |
b32b8144 FG |
177 | typename MutableBufferSequence, typename MutableBufferIterator, |
178 | typename CompletionCondition, typename ReadHandler> | |
7c673cae | 179 | class read_at_op |
1e59de90 TL |
180 | : public base_from_cancellation_state<ReadHandler>, |
181 | base_from_completion_cond<CompletionCondition> | |
7c673cae FG |
182 | { |
183 | public: | |
184 | read_at_op(AsyncRandomAccessReadDevice& device, | |
185 | uint64_t offset, const MutableBufferSequence& buffers, | |
92f5a8d4 | 186 | CompletionCondition& completion_condition, ReadHandler& handler) |
1e59de90 TL |
187 | : base_from_cancellation_state<ReadHandler>( |
188 | handler, enable_partial_cancellation()), | |
189 | base_from_completion_cond<CompletionCondition>(completion_condition), | |
7c673cae FG |
190 | device_(device), |
191 | offset_(offset), | |
192 | buffers_(buffers), | |
193 | start_(0), | |
7c673cae FG |
194 | handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)) |
195 | { | |
196 | } | |
197 | ||
198 | #if defined(BOOST_ASIO_HAS_MOVE) | |
199 | read_at_op(const read_at_op& other) | |
1e59de90 TL |
200 | : base_from_cancellation_state<ReadHandler>(other), |
201 | base_from_completion_cond<CompletionCondition>(other), | |
7c673cae FG |
202 | device_(other.device_), |
203 | offset_(other.offset_), | |
204 | buffers_(other.buffers_), | |
205 | start_(other.start_), | |
7c673cae FG |
206 | handler_(other.handler_) |
207 | { | |
208 | } | |
209 | ||
210 | read_at_op(read_at_op&& other) | |
1e59de90 TL |
211 | : base_from_cancellation_state<ReadHandler>( |
212 | BOOST_ASIO_MOVE_CAST(base_from_cancellation_state< | |
213 | ReadHandler>)(other)), | |
214 | base_from_completion_cond<CompletionCondition>( | |
215 | BOOST_ASIO_MOVE_CAST(base_from_completion_cond< | |
92f5a8d4 | 216 | CompletionCondition>)(other)), |
7c673cae FG |
217 | device_(other.device_), |
218 | offset_(other.offset_), | |
92f5a8d4 | 219 | buffers_(BOOST_ASIO_MOVE_CAST(buffers_type)(other.buffers_)), |
7c673cae | 220 | start_(other.start_), |
7c673cae FG |
221 | handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_)) |
222 | { | |
223 | } | |
224 | #endif // defined(BOOST_ASIO_HAS_MOVE) | |
225 | ||
1e59de90 | 226 | void operator()(boost::system::error_code ec, |
7c673cae FG |
227 | std::size_t bytes_transferred, int start = 0) |
228 | { | |
b32b8144 | 229 | std::size_t max_size; |
7c673cae FG |
230 | switch (start_ = start) |
231 | { | |
232 | case 1: | |
b32b8144 | 233 | max_size = this->check_for_completion(ec, buffers_.total_consumed()); |
1e59de90 | 234 | for (;;) |
7c673cae | 235 | { |
20effc67 TL |
236 | { |
237 | BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at")); | |
238 | device_.async_read_some_at( | |
239 | offset_ + buffers_.total_consumed(), buffers_.prepare(max_size), | |
240 | BOOST_ASIO_MOVE_CAST(read_at_op)(*this)); | |
241 | } | |
7c673cae | 242 | return; default: |
7c673cae | 243 | buffers_.consume(bytes_transferred); |
b32b8144 | 244 | if ((!ec && bytes_transferred == 0) || buffers_.empty()) |
7c673cae | 245 | break; |
b32b8144 | 246 | max_size = this->check_for_completion(ec, buffers_.total_consumed()); |
1e59de90 TL |
247 | if (max_size == 0) |
248 | break; | |
249 | if (this->cancelled() != cancellation_type::none) | |
250 | { | |
251 | ec = boost::asio::error::operation_aborted; | |
252 | break; | |
253 | } | |
254 | } | |
7c673cae | 255 | |
1e59de90 TL |
256 | BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)( |
257 | static_cast<const boost::system::error_code&>(ec), | |
258 | static_cast<const std::size_t&>(buffers_.total_consumed())); | |
7c673cae FG |
259 | } |
260 | } | |
261 | ||
262 | //private: | |
92f5a8d4 TL |
263 | typedef boost::asio::detail::consuming_buffers<mutable_buffer, |
264 | MutableBufferSequence, MutableBufferIterator> buffers_type; | |
265 | ||
7c673cae FG |
266 | AsyncRandomAccessReadDevice& device_; |
267 | uint64_t offset_; | |
92f5a8d4 | 268 | buffers_type buffers_; |
7c673cae | 269 | int start_; |
7c673cae FG |
270 | ReadHandler handler_; |
271 | }; | |
272 | ||
273 | template <typename AsyncRandomAccessReadDevice, | |
b32b8144 | 274 | typename MutableBufferSequence, typename MutableBufferIterator, |
7c673cae | 275 | typename CompletionCondition, typename ReadHandler> |
20effc67 TL |
276 | inline asio_handler_allocate_is_deprecated |
277 | asio_handler_allocate(std::size_t size, | |
7c673cae | 278 | read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence, |
b32b8144 | 279 | MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler) |
7c673cae | 280 | { |
20effc67 TL |
281 | #if defined(BOOST_ASIO_NO_DEPRECATED) |
282 | boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_); | |
283 | return asio_handler_allocate_is_no_longer_used(); | |
284 | #else // defined(BOOST_ASIO_NO_DEPRECATED) | |
7c673cae FG |
285 | return boost_asio_handler_alloc_helpers::allocate( |
286 | size, this_handler->handler_); | |
20effc67 | 287 | #endif // defined(BOOST_ASIO_NO_DEPRECATED) |
7c673cae FG |
288 | } |
289 | ||
290 | template <typename AsyncRandomAccessReadDevice, | |
b32b8144 FG |
291 | typename MutableBufferSequence, typename MutableBufferIterator, |
292 | typename CompletionCondition, typename ReadHandler> | |
20effc67 TL |
293 | inline asio_handler_deallocate_is_deprecated |
294 | asio_handler_deallocate(void* pointer, std::size_t size, | |
7c673cae | 295 | read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence, |
b32b8144 | 296 | MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler) |
7c673cae FG |
297 | { |
298 | boost_asio_handler_alloc_helpers::deallocate( | |
299 | pointer, size, this_handler->handler_); | |
20effc67 TL |
300 | #if defined(BOOST_ASIO_NO_DEPRECATED) |
301 | return asio_handler_deallocate_is_no_longer_used(); | |
302 | #endif // defined(BOOST_ASIO_NO_DEPRECATED) | |
7c673cae FG |
303 | } |
304 | ||
305 | template <typename AsyncRandomAccessReadDevice, | |
b32b8144 FG |
306 | typename MutableBufferSequence, typename MutableBufferIterator, |
307 | typename CompletionCondition, typename ReadHandler> | |
7c673cae FG |
308 | inline bool asio_handler_is_continuation( |
309 | read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence, | |
b32b8144 | 310 | MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler) |
7c673cae FG |
311 | { |
312 | return this_handler->start_ == 0 ? true | |
313 | : boost_asio_handler_cont_helpers::is_continuation( | |
314 | this_handler->handler_); | |
315 | } | |
316 | ||
317 | template <typename Function, typename AsyncRandomAccessReadDevice, | |
b32b8144 FG |
318 | typename MutableBufferSequence, typename MutableBufferIterator, |
319 | typename CompletionCondition, typename ReadHandler> | |
20effc67 TL |
320 | inline asio_handler_invoke_is_deprecated |
321 | asio_handler_invoke(Function& function, | |
7c673cae | 322 | read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence, |
b32b8144 | 323 | MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler) |
7c673cae FG |
324 | { |
325 | boost_asio_handler_invoke_helpers::invoke( | |
326 | function, this_handler->handler_); | |
20effc67 TL |
327 | #if defined(BOOST_ASIO_NO_DEPRECATED) |
328 | return asio_handler_invoke_is_no_longer_used(); | |
329 | #endif // defined(BOOST_ASIO_NO_DEPRECATED) | |
7c673cae FG |
330 | } |
331 | ||
332 | template <typename Function, typename AsyncRandomAccessReadDevice, | |
b32b8144 FG |
333 | typename MutableBufferSequence, typename MutableBufferIterator, |
334 | typename CompletionCondition, typename ReadHandler> | |
20effc67 TL |
335 | inline asio_handler_invoke_is_deprecated |
336 | asio_handler_invoke(const Function& function, | |
7c673cae | 337 | read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence, |
b32b8144 | 338 | MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler) |
7c673cae FG |
339 | { |
340 | boost_asio_handler_invoke_helpers::invoke( | |
341 | function, this_handler->handler_); | |
20effc67 TL |
342 | #if defined(BOOST_ASIO_NO_DEPRECATED) |
343 | return asio_handler_invoke_is_no_longer_used(); | |
344 | #endif // defined(BOOST_ASIO_NO_DEPRECATED) | |
7c673cae FG |
345 | } |
346 | ||
347 | template <typename AsyncRandomAccessReadDevice, | |
b32b8144 FG |
348 | typename MutableBufferSequence, typename MutableBufferIterator, |
349 | typename CompletionCondition, typename ReadHandler> | |
350 | inline void start_read_at_buffer_sequence_op(AsyncRandomAccessReadDevice& d, | |
7c673cae | 351 | uint64_t offset, const MutableBufferSequence& buffers, |
92f5a8d4 | 352 | const MutableBufferIterator&, CompletionCondition& completion_condition, |
b32b8144 | 353 | ReadHandler& handler) |
7c673cae | 354 | { |
b32b8144 FG |
355 | detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence, |
356 | MutableBufferIterator, CompletionCondition, ReadHandler>( | |
357 | d, offset, buffers, completion_condition, handler)( | |
358 | boost::system::error_code(), 0, 1); | |
7c673cae | 359 | } |
92f5a8d4 TL |
360 | |
361 | template <typename AsyncRandomAccessReadDevice> | |
362 | class initiate_async_read_at_buffer_sequence | |
363 | { | |
364 | public: | |
365 | typedef typename AsyncRandomAccessReadDevice::executor_type executor_type; | |
366 | ||
367 | explicit initiate_async_read_at_buffer_sequence( | |
368 | AsyncRandomAccessReadDevice& device) | |
369 | : device_(device) | |
370 | { | |
371 | } | |
372 | ||
373 | executor_type get_executor() const BOOST_ASIO_NOEXCEPT | |
374 | { | |
375 | return device_.get_executor(); | |
376 | } | |
377 | ||
378 | template <typename ReadHandler, typename MutableBufferSequence, | |
379 | typename CompletionCondition> | |
380 | void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, | |
381 | uint64_t offset, const MutableBufferSequence& buffers, | |
382 | BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const | |
383 | { | |
384 | // If you get an error on the following line it means that your handler | |
385 | // does not meet the documented type requirements for a ReadHandler. | |
386 | BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; | |
387 | ||
388 | non_const_lvalue<ReadHandler> handler2(handler); | |
389 | non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); | |
390 | start_read_at_buffer_sequence_op(device_, offset, buffers, | |
391 | boost::asio::buffer_sequence_begin(buffers), | |
392 | completion_cond2.value, handler2.value); | |
393 | } | |
394 | ||
395 | private: | |
396 | AsyncRandomAccessReadDevice& device_; | |
397 | }; | |
7c673cae FG |
398 | } // namespace detail |
399 | ||
b32b8144 FG |
400 | #if !defined(GENERATING_DOCUMENTATION) |
401 | ||
1e59de90 TL |
402 | template <template <typename, typename> class Associator, |
403 | typename AsyncRandomAccessReadDevice, typename MutableBufferSequence, | |
404 | typename MutableBufferIterator, typename CompletionCondition, | |
405 | typename ReadHandler, typename DefaultCandidate> | |
406 | struct associator<Associator, | |
b32b8144 | 407 | detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence, |
1e59de90 TL |
408 | MutableBufferIterator, CompletionCondition, ReadHandler>, |
409 | DefaultCandidate> | |
410 | : Associator<ReadHandler, DefaultCandidate> | |
b32b8144 | 411 | { |
1e59de90 | 412 | static typename Associator<ReadHandler, DefaultCandidate>::type get( |
b32b8144 | 413 | const detail::read_at_op<AsyncRandomAccessReadDevice, |
1e59de90 TL |
414 | MutableBufferSequence, MutableBufferIterator, |
415 | CompletionCondition, ReadHandler>& h, | |
416 | const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT | |
b32b8144 | 417 | { |
1e59de90 | 418 | return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); |
b32b8144 FG |
419 | } |
420 | }; | |
421 | ||
422 | #endif // !defined(GENERATING_DOCUMENTATION) | |
423 | ||
92f5a8d4 TL |
424 | template <typename AsyncRandomAccessReadDevice, |
425 | typename MutableBufferSequence, typename CompletionCondition, | |
426 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, | |
1e59de90 TL |
427 | std::size_t)) ReadToken> |
428 | inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken, | |
7c673cae FG |
429 | void (boost::system::error_code, std::size_t)) |
430 | async_read_at(AsyncRandomAccessReadDevice& d, | |
431 | uint64_t offset, const MutableBufferSequence& buffers, | |
432 | CompletionCondition completion_condition, | |
1e59de90 | 433 | BOOST_ASIO_MOVE_ARG(ReadToken) token) |
7c673cae | 434 | { |
1e59de90 | 435 | return async_initiate<ReadToken, |
92f5a8d4 TL |
436 | void (boost::system::error_code, std::size_t)>( |
437 | detail::initiate_async_read_at_buffer_sequence< | |
438 | AsyncRandomAccessReadDevice>(d), | |
1e59de90 | 439 | token, offset, buffers, |
92f5a8d4 | 440 | BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); |
7c673cae FG |
441 | } |
442 | ||
443 | template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence, | |
92f5a8d4 | 444 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, |
1e59de90 TL |
445 | std::size_t)) ReadToken> |
446 | inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken, | |
7c673cae FG |
447 | void (boost::system::error_code, std::size_t)) |
448 | async_read_at(AsyncRandomAccessReadDevice& d, | |
449 | uint64_t offset, const MutableBufferSequence& buffers, | |
1e59de90 | 450 | BOOST_ASIO_MOVE_ARG(ReadToken) token) |
7c673cae | 451 | { |
1e59de90 | 452 | return async_initiate<ReadToken, |
92f5a8d4 TL |
453 | void (boost::system::error_code, std::size_t)>( |
454 | detail::initiate_async_read_at_buffer_sequence< | |
455 | AsyncRandomAccessReadDevice>(d), | |
1e59de90 | 456 | token, offset, buffers, transfer_all()); |
7c673cae FG |
457 | } |
458 | ||
b32b8144 | 459 | #if !defined(BOOST_ASIO_NO_EXTENSIONS) |
7c673cae FG |
460 | #if !defined(BOOST_ASIO_NO_IOSTREAM) |
461 | ||
462 | namespace detail | |
463 | { | |
464 | template <typename AsyncRandomAccessReadDevice, typename Allocator, | |
465 | typename CompletionCondition, typename ReadHandler> | |
466 | class read_at_streambuf_op | |
1e59de90 TL |
467 | : public base_from_cancellation_state<ReadHandler>, |
468 | base_from_completion_cond<CompletionCondition> | |
7c673cae FG |
469 | { |
470 | public: | |
471 | read_at_streambuf_op(AsyncRandomAccessReadDevice& device, | |
472 | uint64_t offset, basic_streambuf<Allocator>& streambuf, | |
92f5a8d4 | 473 | CompletionCondition& completion_condition, ReadHandler& handler) |
1e59de90 TL |
474 | : base_from_cancellation_state<ReadHandler>( |
475 | handler, enable_partial_cancellation()), | |
476 | base_from_completion_cond<CompletionCondition>(completion_condition), | |
7c673cae FG |
477 | device_(device), |
478 | offset_(offset), | |
479 | streambuf_(streambuf), | |
480 | start_(0), | |
481 | total_transferred_(0), | |
482 | handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)) | |
483 | { | |
484 | } | |
485 | ||
486 | #if defined(BOOST_ASIO_HAS_MOVE) | |
487 | read_at_streambuf_op(const read_at_streambuf_op& other) | |
1e59de90 TL |
488 | : base_from_cancellation_state<ReadHandler>(other), |
489 | base_from_completion_cond<CompletionCondition>(other), | |
7c673cae FG |
490 | device_(other.device_), |
491 | offset_(other.offset_), | |
492 | streambuf_(other.streambuf_), | |
493 | start_(other.start_), | |
494 | total_transferred_(other.total_transferred_), | |
495 | handler_(other.handler_) | |
496 | { | |
497 | } | |
498 | ||
499 | read_at_streambuf_op(read_at_streambuf_op&& other) | |
1e59de90 TL |
500 | : base_from_cancellation_state<ReadHandler>( |
501 | BOOST_ASIO_MOVE_CAST(base_from_cancellation_state< | |
502 | ReadHandler>)(other)), | |
503 | base_from_completion_cond<CompletionCondition>( | |
504 | BOOST_ASIO_MOVE_CAST(base_from_completion_cond< | |
92f5a8d4 | 505 | CompletionCondition>)(other)), |
7c673cae FG |
506 | device_(other.device_), |
507 | offset_(other.offset_), | |
508 | streambuf_(other.streambuf_), | |
509 | start_(other.start_), | |
510 | total_transferred_(other.total_transferred_), | |
511 | handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_)) | |
512 | { | |
513 | } | |
514 | #endif // defined(BOOST_ASIO_HAS_MOVE) | |
515 | ||
1e59de90 | 516 | void operator()(boost::system::error_code ec, |
7c673cae FG |
517 | std::size_t bytes_transferred, int start = 0) |
518 | { | |
519 | std::size_t max_size, bytes_available; | |
520 | switch (start_ = start) | |
521 | { | |
522 | case 1: | |
523 | max_size = this->check_for_completion(ec, total_transferred_); | |
524 | bytes_available = read_size_helper(streambuf_, max_size); | |
525 | for (;;) | |
526 | { | |
20effc67 TL |
527 | { |
528 | BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at")); | |
529 | device_.async_read_some_at(offset_ + total_transferred_, | |
530 | streambuf_.prepare(bytes_available), | |
531 | BOOST_ASIO_MOVE_CAST(read_at_streambuf_op)(*this)); | |
532 | } | |
7c673cae FG |
533 | return; default: |
534 | total_transferred_ += bytes_transferred; | |
535 | streambuf_.commit(bytes_transferred); | |
536 | max_size = this->check_for_completion(ec, total_transferred_); | |
537 | bytes_available = read_size_helper(streambuf_, max_size); | |
538 | if ((!ec && bytes_transferred == 0) || bytes_available == 0) | |
539 | break; | |
1e59de90 TL |
540 | if (this->cancelled() != cancellation_type::none) |
541 | { | |
542 | ec = boost::asio::error::operation_aborted; | |
543 | break; | |
544 | } | |
7c673cae FG |
545 | } |
546 | ||
1e59de90 TL |
547 | BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)( |
548 | static_cast<const boost::system::error_code&>(ec), | |
549 | static_cast<const std::size_t&>(total_transferred_)); | |
7c673cae FG |
550 | } |
551 | } | |
552 | ||
553 | //private: | |
554 | AsyncRandomAccessReadDevice& device_; | |
555 | uint64_t offset_; | |
556 | boost::asio::basic_streambuf<Allocator>& streambuf_; | |
557 | int start_; | |
558 | std::size_t total_transferred_; | |
559 | ReadHandler handler_; | |
560 | }; | |
561 | ||
562 | template <typename AsyncRandomAccessReadDevice, typename Allocator, | |
563 | typename CompletionCondition, typename ReadHandler> | |
20effc67 TL |
564 | inline asio_handler_allocate_is_deprecated |
565 | asio_handler_allocate(std::size_t size, | |
7c673cae FG |
566 | read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator, |
567 | CompletionCondition, ReadHandler>* this_handler) | |
568 | { | |
20effc67 TL |
569 | #if defined(BOOST_ASIO_NO_DEPRECATED) |
570 | boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_); | |
571 | return asio_handler_allocate_is_no_longer_used(); | |
572 | #else // defined(BOOST_ASIO_NO_DEPRECATED) | |
7c673cae FG |
573 | return boost_asio_handler_alloc_helpers::allocate( |
574 | size, this_handler->handler_); | |
20effc67 | 575 | #endif // defined(BOOST_ASIO_NO_DEPRECATED) |
7c673cae FG |
576 | } |
577 | ||
578 | template <typename AsyncRandomAccessReadDevice, typename Allocator, | |
579 | typename CompletionCondition, typename ReadHandler> | |
20effc67 TL |
580 | inline asio_handler_deallocate_is_deprecated |
581 | asio_handler_deallocate(void* pointer, std::size_t size, | |
7c673cae FG |
582 | read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator, |
583 | CompletionCondition, ReadHandler>* this_handler) | |
584 | { | |
585 | boost_asio_handler_alloc_helpers::deallocate( | |
586 | pointer, size, this_handler->handler_); | |
20effc67 TL |
587 | #if defined(BOOST_ASIO_NO_DEPRECATED) |
588 | return asio_handler_deallocate_is_no_longer_used(); | |
589 | #endif // defined(BOOST_ASIO_NO_DEPRECATED) | |
7c673cae FG |
590 | } |
591 | ||
592 | template <typename AsyncRandomAccessReadDevice, typename Allocator, | |
593 | typename CompletionCondition, typename ReadHandler> | |
594 | inline bool asio_handler_is_continuation( | |
595 | read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator, | |
596 | CompletionCondition, ReadHandler>* this_handler) | |
597 | { | |
598 | return this_handler->start_ == 0 ? true | |
599 | : boost_asio_handler_cont_helpers::is_continuation( | |
600 | this_handler->handler_); | |
601 | } | |
602 | ||
603 | template <typename Function, typename AsyncRandomAccessReadDevice, | |
604 | typename Allocator, typename CompletionCondition, typename ReadHandler> | |
20effc67 TL |
605 | inline asio_handler_invoke_is_deprecated |
606 | asio_handler_invoke(Function& function, | |
7c673cae FG |
607 | read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator, |
608 | CompletionCondition, ReadHandler>* this_handler) | |
609 | { | |
610 | boost_asio_handler_invoke_helpers::invoke( | |
611 | function, this_handler->handler_); | |
20effc67 TL |
612 | #if defined(BOOST_ASIO_NO_DEPRECATED) |
613 | return asio_handler_invoke_is_no_longer_used(); | |
614 | #endif // defined(BOOST_ASIO_NO_DEPRECATED) | |
7c673cae FG |
615 | } |
616 | ||
617 | template <typename Function, typename AsyncRandomAccessReadDevice, | |
618 | typename Allocator, typename CompletionCondition, typename ReadHandler> | |
20effc67 TL |
619 | inline asio_handler_invoke_is_deprecated |
620 | asio_handler_invoke(const Function& function, | |
7c673cae FG |
621 | read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator, |
622 | CompletionCondition, ReadHandler>* this_handler) | |
623 | { | |
624 | boost_asio_handler_invoke_helpers::invoke( | |
625 | function, this_handler->handler_); | |
20effc67 TL |
626 | #if defined(BOOST_ASIO_NO_DEPRECATED) |
627 | return asio_handler_invoke_is_no_longer_used(); | |
628 | #endif // defined(BOOST_ASIO_NO_DEPRECATED) | |
7c673cae | 629 | } |
92f5a8d4 TL |
630 | |
631 | template <typename AsyncRandomAccessReadDevice> | |
632 | class initiate_async_read_at_streambuf | |
633 | { | |
634 | public: | |
635 | typedef typename AsyncRandomAccessReadDevice::executor_type executor_type; | |
636 | ||
637 | explicit initiate_async_read_at_streambuf( | |
638 | AsyncRandomAccessReadDevice& device) | |
639 | : device_(device) | |
640 | { | |
641 | } | |
642 | ||
643 | executor_type get_executor() const BOOST_ASIO_NOEXCEPT | |
644 | { | |
645 | return device_.get_executor(); | |
646 | } | |
647 | ||
648 | template <typename ReadHandler, | |
649 | typename Allocator, typename CompletionCondition> | |
650 | void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, | |
651 | uint64_t offset, basic_streambuf<Allocator>* b, | |
652 | BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const | |
653 | { | |
654 | // If you get an error on the following line it means that your handler | |
655 | // does not meet the documented type requirements for a ReadHandler. | |
656 | BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; | |
657 | ||
658 | non_const_lvalue<ReadHandler> handler2(handler); | |
659 | non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); | |
660 | read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator, | |
661 | CompletionCondition, typename decay<ReadHandler>::type>( | |
662 | device_, offset, *b, completion_cond2.value, handler2.value)( | |
663 | boost::system::error_code(), 0, 1); | |
664 | } | |
665 | ||
666 | private: | |
667 | AsyncRandomAccessReadDevice& device_; | |
668 | }; | |
7c673cae FG |
669 | } // namespace detail |
670 | ||
b32b8144 FG |
671 | #if !defined(GENERATING_DOCUMENTATION) |
672 | ||
1e59de90 TL |
673 | template <template <typename, typename> class Associator, |
674 | typename AsyncRandomAccessReadDevice, typename Executor, | |
675 | typename CompletionCondition, typename ReadHandler, | |
676 | typename DefaultCandidate> | |
677 | struct associator<Associator, | |
b32b8144 FG |
678 | detail::read_at_streambuf_op<AsyncRandomAccessReadDevice, |
679 | Executor, CompletionCondition, ReadHandler>, | |
1e59de90 TL |
680 | DefaultCandidate> |
681 | : Associator<ReadHandler, DefaultCandidate> | |
b32b8144 | 682 | { |
1e59de90 | 683 | static typename Associator<ReadHandler, DefaultCandidate>::type get( |
b32b8144 FG |
684 | const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice, |
685 | Executor, CompletionCondition, ReadHandler>& h, | |
1e59de90 | 686 | const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT |
b32b8144 | 687 | { |
1e59de90 | 688 | return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); |
b32b8144 FG |
689 | } |
690 | }; | |
691 | ||
692 | #endif // !defined(GENERATING_DOCUMENTATION) | |
693 | ||
92f5a8d4 TL |
694 | template <typename AsyncRandomAccessReadDevice, |
695 | typename Allocator, typename CompletionCondition, | |
696 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, | |
1e59de90 TL |
697 | std::size_t)) ReadToken> |
698 | inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken, | |
7c673cae FG |
699 | void (boost::system::error_code, std::size_t)) |
700 | async_read_at(AsyncRandomAccessReadDevice& d, | |
701 | uint64_t offset, boost::asio::basic_streambuf<Allocator>& b, | |
702 | CompletionCondition completion_condition, | |
1e59de90 | 703 | BOOST_ASIO_MOVE_ARG(ReadToken) token) |
7c673cae | 704 | { |
1e59de90 | 705 | return async_initiate<ReadToken, |
92f5a8d4 TL |
706 | void (boost::system::error_code, std::size_t)>( |
707 | detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d), | |
1e59de90 | 708 | token, offset, &b, |
92f5a8d4 | 709 | BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); |
7c673cae FG |
710 | } |
711 | ||
712 | template <typename AsyncRandomAccessReadDevice, typename Allocator, | |
92f5a8d4 | 713 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, |
1e59de90 TL |
714 | std::size_t)) ReadToken> |
715 | inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken, | |
7c673cae FG |
716 | void (boost::system::error_code, std::size_t)) |
717 | async_read_at(AsyncRandomAccessReadDevice& d, | |
718 | uint64_t offset, boost::asio::basic_streambuf<Allocator>& b, | |
1e59de90 | 719 | BOOST_ASIO_MOVE_ARG(ReadToken) token) |
7c673cae | 720 | { |
1e59de90 | 721 | return async_initiate<ReadToken, |
92f5a8d4 TL |
722 | void (boost::system::error_code, std::size_t)>( |
723 | detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d), | |
1e59de90 | 724 | token, offset, &b, transfer_all()); |
7c673cae FG |
725 | } |
726 | ||
727 | #endif // !defined(BOOST_ASIO_NO_IOSTREAM) | |
b32b8144 | 728 | #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) |
7c673cae FG |
729 | |
730 | } // namespace asio | |
731 | } // namespace boost | |
732 | ||
733 | #include <boost/asio/detail/pop_options.hpp> | |
734 | ||
735 | #endif // BOOST_ASIO_IMPL_READ_AT_HPP |