1 | // |
2 | // impl/write_at.hpp |
3 | // ~~~~~~~~~~~~~~~~~ |
4 | // |
5 | // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
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_WRITE_AT_HPP |
12 | #define BOOST_ASIO_IMPL_WRITE_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 <boost/asio/buffer.hpp> |
19 | #include <boost/asio/completion_condition.hpp> |
20 | #include <boost/asio/detail/array_fwd.hpp> |
21 | #include <boost/asio/detail/base_from_completion_cond.hpp> |
22 | #include <boost/asio/detail/bind_handler.hpp> |
23 | #include <boost/asio/detail/consuming_buffers.hpp> |
24 | #include <boost/asio/detail/dependent_type.hpp> |
25 | #include <boost/asio/detail/handler_alloc_helpers.hpp> |
26 | #include <boost/asio/detail/handler_cont_helpers.hpp> |
27 | #include <boost/asio/detail/handler_invoke_helpers.hpp> |
28 | #include <boost/asio/detail/handler_type_requirements.hpp> |
29 | #include <boost/asio/detail/throw_error.hpp> |
30 | |
31 | #include <boost/asio/detail/push_options.hpp> |
32 | |
33 | namespace boost { |
34 | namespace asio { |
35 | |
36 | template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence, |
37 | typename CompletionCondition> |
38 | std::size_t write_at(SyncRandomAccessWriteDevice& d, |
39 | uint64_t offset, const ConstBufferSequence& buffers, |
40 | CompletionCondition completion_condition, boost::system::error_code& ec) |
41 | { |
42 | ec = boost::system::error_code(); |
43 | boost::asio::detail::consuming_buffers< |
44 | const_buffer, ConstBufferSequence> tmp(buffers); |
45 | std::size_t total_transferred = 0; |
46 | tmp.prepare(detail::adapt_completion_condition_result( |
47 | completion_condition(ec, total_transferred))); |
48 | while (tmp.begin() != tmp.end()) |
49 | { |
50 | std::size_t bytes_transferred = d.write_some_at( |
51 | offset + total_transferred, tmp, ec); |
52 | tmp.consume(bytes_transferred); |
53 | total_transferred += bytes_transferred; |
54 | tmp.prepare(detail::adapt_completion_condition_result( |
55 | completion_condition(ec, total_transferred))); |
56 | } |
57 | return total_transferred; |
58 | } |
59 | |
60 | template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence> |
61 | inline std::size_t write_at(SyncRandomAccessWriteDevice& d, |
62 | uint64_t offset, const ConstBufferSequence& buffers) |
63 | { |
64 | boost::system::error_code ec; |
65 | std::size_t bytes_transferred = write_at( |
66 | d, offset, buffers, transfer_all(), ec); |
67 | boost::asio::detail::throw_error(ec, "write_at" ); |
68 | return bytes_transferred; |
69 | } |
70 | |
71 | template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence> |
72 | inline std::size_t write_at(SyncRandomAccessWriteDevice& d, |
73 | uint64_t offset, const ConstBufferSequence& buffers, |
74 | boost::system::error_code& ec) |
75 | { |
76 | return write_at(d, offset, buffers, transfer_all(), ec); |
77 | } |
78 | |
79 | template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence, |
80 | typename CompletionCondition> |
81 | inline std::size_t write_at(SyncRandomAccessWriteDevice& d, |
82 | uint64_t offset, const ConstBufferSequence& buffers, |
83 | CompletionCondition completion_condition) |
84 | { |
85 | boost::system::error_code ec; |
86 | std::size_t bytes_transferred = write_at( |
87 | d, offset, buffers, completion_condition, ec); |
88 | boost::asio::detail::throw_error(ec, "write_at" ); |
89 | return bytes_transferred; |
90 | } |
91 | |
92 | #if !defined(BOOST_ASIO_NO_IOSTREAM) |
93 | |
94 | template <typename SyncRandomAccessWriteDevice, typename Allocator, |
95 | typename CompletionCondition> |
96 | std::size_t write_at(SyncRandomAccessWriteDevice& d, |
97 | uint64_t offset, boost::asio::basic_streambuf<Allocator>& b, |
98 | CompletionCondition completion_condition, boost::system::error_code& ec) |
99 | { |
100 | std::size_t bytes_transferred = write_at( |
101 | d, offset, b.data(), completion_condition, ec); |
102 | b.consume(bytes_transferred); |
103 | return bytes_transferred; |
104 | } |
105 | |
106 | template <typename SyncRandomAccessWriteDevice, typename Allocator> |
107 | inline std::size_t write_at(SyncRandomAccessWriteDevice& d, |
108 | uint64_t offset, boost::asio::basic_streambuf<Allocator>& b) |
109 | { |
110 | boost::system::error_code ec; |
111 | std::size_t bytes_transferred = write_at(d, offset, b, transfer_all(), ec); |
112 | boost::asio::detail::throw_error(ec, "write_at" ); |
113 | return bytes_transferred; |
114 | } |
115 | |
116 | template <typename SyncRandomAccessWriteDevice, typename Allocator> |
117 | inline std::size_t write_at(SyncRandomAccessWriteDevice& d, |
118 | uint64_t offset, boost::asio::basic_streambuf<Allocator>& b, |
119 | boost::system::error_code& ec) |
120 | { |
121 | return write_at(d, offset, b, transfer_all(), ec); |
122 | } |
123 | |
124 | template <typename SyncRandomAccessWriteDevice, typename Allocator, |
125 | typename CompletionCondition> |
126 | inline std::size_t write_at(SyncRandomAccessWriteDevice& d, |
127 | uint64_t offset, boost::asio::basic_streambuf<Allocator>& b, |
128 | CompletionCondition completion_condition) |
129 | { |
130 | boost::system::error_code ec; |
131 | std::size_t bytes_transferred = write_at( |
132 | d, offset, b, completion_condition, ec); |
133 | boost::asio::detail::throw_error(ec, "write_at" ); |
134 | return bytes_transferred; |
135 | } |
136 | |
137 | #endif // !defined(BOOST_ASIO_NO_IOSTREAM) |
138 | |
139 | namespace detail |
140 | { |
141 | template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence, |
142 | typename CompletionCondition, typename WriteHandler> |
143 | class write_at_op |
144 | : detail::base_from_completion_cond<CompletionCondition> |
145 | { |
146 | public: |
147 | write_at_op(AsyncRandomAccessWriteDevice& device, |
148 | uint64_t offset, const ConstBufferSequence& buffers, |
149 | CompletionCondition completion_condition, WriteHandler& handler) |
150 | : detail::base_from_completion_cond< |
151 | CompletionCondition>(completion_condition), |
152 | device_(device), |
153 | offset_(offset), |
154 | buffers_(buffers), |
155 | start_(0), |
156 | total_transferred_(0), |
157 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)) |
158 | { |
159 | } |
160 | |
161 | #if defined(BOOST_ASIO_HAS_MOVE) |
162 | write_at_op(const write_at_op& other) |
163 | : detail::base_from_completion_cond<CompletionCondition>(other), |
164 | device_(other.device_), |
165 | offset_(other.offset_), |
166 | buffers_(other.buffers_), |
167 | start_(other.start_), |
168 | total_transferred_(other.total_transferred_), |
169 | handler_(other.handler_) |
170 | { |
171 | } |
172 | |
173 | write_at_op(write_at_op&& other) |
174 | : detail::base_from_completion_cond<CompletionCondition>(other), |
175 | device_(other.device_), |
176 | offset_(other.offset_), |
177 | buffers_(other.buffers_), |
178 | start_(other.start_), |
179 | total_transferred_(other.total_transferred_), |
180 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_)) |
181 | { |
182 | } |
183 | #endif // defined(BOOST_ASIO_HAS_MOVE) |
184 | |
185 | void operator()(const boost::system::error_code& ec, |
186 | std::size_t bytes_transferred, int start = 0) |
187 | { |
188 | switch (start_ = start) |
189 | { |
190 | case 1: |
191 | buffers_.prepare(this->check_for_completion(ec, total_transferred_)); |
192 | for (;;) |
193 | { |
194 | device_.async_write_some_at( |
195 | offset_ + total_transferred_, buffers_, |
196 | BOOST_ASIO_MOVE_CAST(write_at_op)(*this)); |
197 | return; default: |
198 | total_transferred_ += bytes_transferred; |
199 | buffers_.consume(bytes_transferred); |
200 | buffers_.prepare(this->check_for_completion(ec, total_transferred_)); |
201 | if ((!ec && bytes_transferred == 0) |
202 | || buffers_.begin() == buffers_.end()) |
203 | break; |
204 | } |
205 | |
206 | handler_(ec, static_cast<const std::size_t&>(total_transferred_)); |
207 | } |
208 | } |
209 | |
210 | //private: |
211 | AsyncRandomAccessWriteDevice& device_; |
212 | uint64_t offset_; |
213 | boost::asio::detail::consuming_buffers< |
214 | const_buffer, ConstBufferSequence> buffers_; |
215 | int start_; |
216 | std::size_t total_transferred_; |
217 | WriteHandler handler_; |
218 | }; |
219 | |
220 | template <typename AsyncRandomAccessWriteDevice, |
221 | typename CompletionCondition, typename WriteHandler> |
222 | class write_at_op<AsyncRandomAccessWriteDevice, |
223 | boost::asio::mutable_buffers_1, CompletionCondition, WriteHandler> |
224 | : detail::base_from_completion_cond<CompletionCondition> |
225 | { |
226 | public: |
227 | write_at_op(AsyncRandomAccessWriteDevice& device, |
228 | uint64_t offset, const boost::asio::mutable_buffers_1& buffers, |
229 | CompletionCondition completion_condition, |
230 | WriteHandler& handler) |
231 | : detail::base_from_completion_cond< |
232 | CompletionCondition>(completion_condition), |
233 | device_(device), |
234 | offset_(offset), |
235 | buffer_(buffers), |
236 | start_(0), |
237 | total_transferred_(0), |
238 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)) |
239 | { |
240 | } |
241 | |
242 | #if defined(BOOST_ASIO_HAS_MOVE) |
243 | write_at_op(const write_at_op& other) |
244 | : detail::base_from_completion_cond<CompletionCondition>(other), |
245 | device_(other.device_), |
246 | offset_(other.offset_), |
247 | buffer_(other.buffer_), |
248 | start_(other.start_), |
249 | total_transferred_(other.total_transferred_), |
250 | handler_(other.handler_) |
251 | { |
252 | } |
253 | |
254 | write_at_op(write_at_op&& other) |
255 | : detail::base_from_completion_cond<CompletionCondition>(other), |
256 | device_(other.device_), |
257 | offset_(other.offset_), |
258 | buffer_(other.buffer_), |
259 | start_(other.start_), |
260 | total_transferred_(other.total_transferred_), |
261 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_)) |
262 | { |
263 | } |
264 | #endif // defined(BOOST_ASIO_HAS_MOVE) |
265 | |
266 | void operator()(const boost::system::error_code& ec, |
267 | std::size_t bytes_transferred, int start = 0) |
268 | { |
269 | std::size_t n = 0; |
270 | switch (start_ = start) |
271 | { |
272 | case 1: |
273 | n = this->check_for_completion(ec, total_transferred_); |
274 | for (;;) |
275 | { |
276 | device_.async_write_some_at(offset_ + total_transferred_, |
277 | boost::asio::buffer(buffer_ + total_transferred_, n), |
278 | BOOST_ASIO_MOVE_CAST(write_at_op)(*this)); |
279 | return; default: |
280 | total_transferred_ += bytes_transferred; |
281 | if ((!ec && bytes_transferred == 0) |
282 | || (n = this->check_for_completion(ec, total_transferred_)) == 0 |
283 | || total_transferred_ == boost::asio::buffer_size(buffer_)) |
284 | break; |
285 | } |
286 | |
287 | handler_(ec, static_cast<const std::size_t&>(total_transferred_)); |
288 | } |
289 | } |
290 | |
291 | //private: |
292 | AsyncRandomAccessWriteDevice& device_; |
293 | uint64_t offset_; |
294 | boost::asio::mutable_buffer buffer_; |
295 | int start_; |
296 | std::size_t total_transferred_; |
297 | WriteHandler handler_; |
298 | }; |
299 | |
300 | template <typename AsyncRandomAccessWriteDevice, |
301 | typename CompletionCondition, typename WriteHandler> |
302 | class write_at_op<AsyncRandomAccessWriteDevice, boost::asio::const_buffers_1, |
303 | CompletionCondition, WriteHandler> |
304 | : detail::base_from_completion_cond<CompletionCondition> |
305 | { |
306 | public: |
307 | write_at_op(AsyncRandomAccessWriteDevice& device, |
308 | uint64_t offset, const boost::asio::const_buffers_1& buffers, |
309 | CompletionCondition completion_condition, |
310 | WriteHandler& handler) |
311 | : detail::base_from_completion_cond< |
312 | CompletionCondition>(completion_condition), |
313 | device_(device), |
314 | offset_(offset), |
315 | buffer_(buffers), |
316 | start_(0), |
317 | total_transferred_(0), |
318 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)) |
319 | { |
320 | } |
321 | |
322 | #if defined(BOOST_ASIO_HAS_MOVE) |
323 | write_at_op(const write_at_op& other) |
324 | : detail::base_from_completion_cond<CompletionCondition>(other), |
325 | device_(other.device_), |
326 | offset_(other.offset_), |
327 | buffer_(other.buffer_), |
328 | start_(other.start_), |
329 | total_transferred_(other.total_transferred_), |
330 | handler_(other.handler_) |
331 | { |
332 | } |
333 | |
334 | write_at_op(write_at_op&& other) |
335 | : detail::base_from_completion_cond<CompletionCondition>(other), |
336 | device_(other.device_), |
337 | offset_(other.offset_), |
338 | buffer_(other.buffer_), |
339 | start_(other.start_), |
340 | total_transferred_(other.total_transferred_), |
341 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_)) |
342 | { |
343 | } |
344 | #endif // defined(BOOST_ASIO_HAS_MOVE) |
345 | |
346 | void operator()(const boost::system::error_code& ec, |
347 | std::size_t bytes_transferred, int start = 0) |
348 | { |
349 | std::size_t n = 0; |
350 | switch (start_ = start) |
351 | { |
352 | case 1: |
353 | n = this->check_for_completion(ec, total_transferred_); |
354 | for (;;) |
355 | { |
356 | device_.async_write_some_at(offset_ + total_transferred_, |
357 | boost::asio::buffer(buffer_ + total_transferred_, n), |
358 | BOOST_ASIO_MOVE_CAST(write_at_op)(*this)); |
359 | return; default: |
360 | total_transferred_ += bytes_transferred; |
361 | if ((!ec && bytes_transferred == 0) |
362 | || (n = this->check_for_completion(ec, total_transferred_)) == 0 |
363 | || total_transferred_ == boost::asio::buffer_size(buffer_)) |
364 | break; |
365 | } |
366 | |
367 | handler_(ec, static_cast<const std::size_t&>(total_transferred_)); |
368 | } |
369 | } |
370 | |
371 | //private: |
372 | AsyncRandomAccessWriteDevice& device_; |
373 | uint64_t offset_; |
374 | boost::asio::const_buffer buffer_; |
375 | int start_; |
376 | std::size_t total_transferred_; |
377 | WriteHandler handler_; |
378 | }; |
379 | |
380 | template <typename AsyncRandomAccessWriteDevice, typename Elem, |
381 | typename CompletionCondition, typename WriteHandler> |
382 | class write_at_op<AsyncRandomAccessWriteDevice, boost::array<Elem, 2>, |
383 | CompletionCondition, WriteHandler> |
384 | : detail::base_from_completion_cond<CompletionCondition> |
385 | { |
386 | public: |
387 | write_at_op(AsyncRandomAccessWriteDevice& device, |
388 | uint64_t offset, const boost::array<Elem, 2>& buffers, |
389 | CompletionCondition completion_condition, WriteHandler& handler) |
390 | : detail::base_from_completion_cond< |
391 | CompletionCondition>(completion_condition), |
392 | device_(device), |
393 | offset_(offset), |
394 | buffers_(buffers), |
395 | start_(0), |
396 | total_transferred_(0), |
397 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)) |
398 | { |
399 | } |
400 | |
401 | #if defined(BOOST_ASIO_HAS_MOVE) |
402 | write_at_op(const write_at_op& other) |
403 | : detail::base_from_completion_cond<CompletionCondition>(other), |
404 | device_(other.device_), |
405 | offset_(other.offset_), |
406 | buffers_(other.buffers_), |
407 | start_(other.start_), |
408 | total_transferred_(other.total_transferred_), |
409 | handler_(other.handler_) |
410 | { |
411 | } |
412 | |
413 | write_at_op(write_at_op&& other) |
414 | : detail::base_from_completion_cond<CompletionCondition>(other), |
415 | device_(other.device_), |
416 | offset_(other.offset_), |
417 | buffers_(other.buffers_), |
418 | start_(other.start_), |
419 | total_transferred_(other.total_transferred_), |
420 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_)) |
421 | { |
422 | } |
423 | #endif // defined(BOOST_ASIO_HAS_MOVE) |
424 | |
425 | void operator()(const boost::system::error_code& ec, |
426 | std::size_t bytes_transferred, int start = 0) |
427 | { |
428 | typename boost::asio::detail::dependent_type<Elem, |
429 | boost::array<boost::asio::const_buffer, 2> >::type bufs = {{ |
430 | boost::asio::const_buffer(buffers_[0]), |
431 | boost::asio::const_buffer(buffers_[1]) }}; |
432 | std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]); |
433 | std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]); |
434 | std::size_t n = 0; |
435 | switch (start_ = start) |
436 | { |
437 | case 1: |
438 | n = this->check_for_completion(ec, total_transferred_); |
439 | for (;;) |
440 | { |
441 | bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n); |
442 | bufs[1] = boost::asio::buffer( |
443 | bufs[1] + (total_transferred_ < buffer_size0 |
444 | ? 0 : total_transferred_ - buffer_size0), |
445 | n - boost::asio::buffer_size(bufs[0])); |
446 | device_.async_write_some_at(offset_ + total_transferred_, |
447 | bufs, BOOST_ASIO_MOVE_CAST(write_at_op)(*this)); |
448 | return; default: |
449 | total_transferred_ += bytes_transferred; |
450 | if ((!ec && bytes_transferred == 0) |
451 | || (n = this->check_for_completion(ec, total_transferred_)) == 0 |
452 | || total_transferred_ == buffer_size0 + buffer_size1) |
453 | break; |
454 | } |
455 | |
456 | handler_(ec, static_cast<const std::size_t&>(total_transferred_)); |
457 | } |
458 | } |
459 | |
460 | //private: |
461 | AsyncRandomAccessWriteDevice& device_; |
462 | uint64_t offset_; |
463 | boost::array<Elem, 2> buffers_; |
464 | int start_; |
465 | std::size_t total_transferred_; |
466 | WriteHandler handler_; |
467 | }; |
468 | |
469 | #if defined(BOOST_ASIO_HAS_STD_ARRAY) |
470 | |
471 | template <typename AsyncRandomAccessWriteDevice, typename Elem, |
472 | typename CompletionCondition, typename WriteHandler> |
473 | class write_at_op<AsyncRandomAccessWriteDevice, std::array<Elem, 2>, |
474 | CompletionCondition, WriteHandler> |
475 | : detail::base_from_completion_cond<CompletionCondition> |
476 | { |
477 | public: |
478 | write_at_op(AsyncRandomAccessWriteDevice& device, |
479 | uint64_t offset, const std::array<Elem, 2>& buffers, |
480 | CompletionCondition completion_condition, WriteHandler& handler) |
481 | : detail::base_from_completion_cond< |
482 | CompletionCondition>(completion_condition), |
483 | device_(device), |
484 | offset_(offset), |
485 | buffers_(buffers), |
486 | start_(0), |
487 | total_transferred_(0), |
488 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)) |
489 | { |
490 | } |
491 | |
492 | #if defined(BOOST_ASIO_HAS_MOVE) |
493 | write_at_op(const write_at_op& other) |
494 | : detail::base_from_completion_cond<CompletionCondition>(other), |
495 | device_(other.device_), |
496 | offset_(other.offset_), |
497 | buffers_(other.buffers_), |
498 | start_(other.start_), |
499 | total_transferred_(other.total_transferred_), |
500 | handler_(other.handler_) |
501 | { |
502 | } |
503 | |
504 | write_at_op(write_at_op&& other) |
505 | : detail::base_from_completion_cond<CompletionCondition>(other), |
506 | device_(other.device_), |
507 | offset_(other.offset_), |
508 | buffers_(other.buffers_), |
509 | start_(other.start_), |
510 | total_transferred_(other.total_transferred_), |
511 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_)) |
512 | { |
513 | } |
514 | #endif // defined(BOOST_ASIO_HAS_MOVE) |
515 | |
516 | void operator()(const boost::system::error_code& ec, |
517 | std::size_t bytes_transferred, int start = 0) |
518 | { |
519 | typename boost::asio::detail::dependent_type<Elem, |
520 | std::array<boost::asio::const_buffer, 2> >::type bufs = {{ |
521 | boost::asio::const_buffer(buffers_[0]), |
522 | boost::asio::const_buffer(buffers_[1]) }}; |
523 | std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]); |
524 | std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]); |
525 | std::size_t n = 0; |
526 | switch (start_ = start) |
527 | { |
528 | case 1: |
529 | n = this->check_for_completion(ec, total_transferred_); |
530 | for (;;) |
531 | { |
532 | bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n); |
533 | bufs[1] = boost::asio::buffer( |
534 | bufs[1] + (total_transferred_ < buffer_size0 |
535 | ? 0 : total_transferred_ - buffer_size0), |
536 | n - boost::asio::buffer_size(bufs[0])); |
537 | device_.async_write_some_at(offset_ + total_transferred_, |
538 | bufs, BOOST_ASIO_MOVE_CAST(write_at_op)(*this)); |
539 | return; default: |
540 | total_transferred_ += bytes_transferred; |
541 | if ((!ec && bytes_transferred == 0) |
542 | || (n = this->check_for_completion(ec, total_transferred_)) == 0 |
543 | || total_transferred_ == buffer_size0 + buffer_size1) |
544 | break; |
545 | } |
546 | |
547 | handler_(ec, static_cast<const std::size_t&>(total_transferred_)); |
548 | } |
549 | } |
550 | |
551 | //private: |
552 | AsyncRandomAccessWriteDevice& device_; |
553 | uint64_t offset_; |
554 | std::array<Elem, 2> buffers_; |
555 | int start_; |
556 | std::size_t total_transferred_; |
557 | WriteHandler handler_; |
558 | }; |
559 | |
560 | #endif // defined(BOOST_ASIO_HAS_STD_ARRAY) |
561 | |
562 | template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence, |
563 | typename CompletionCondition, typename WriteHandler> |
564 | inline void* asio_handler_allocate(std::size_t size, |
565 | write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence, |
566 | CompletionCondition, WriteHandler>* this_handler) |
567 | { |
568 | return boost_asio_handler_alloc_helpers::allocate( |
569 | size, this_handler->handler_); |
570 | } |
571 | |
572 | template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence, |
573 | typename CompletionCondition, typename WriteHandler> |
574 | inline void asio_handler_deallocate(void* pointer, std::size_t size, |
575 | write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence, |
576 | CompletionCondition, WriteHandler>* this_handler) |
577 | { |
578 | boost_asio_handler_alloc_helpers::deallocate( |
579 | pointer, size, this_handler->handler_); |
580 | } |
581 | |
582 | template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence, |
583 | typename CompletionCondition, typename WriteHandler> |
584 | inline bool asio_handler_is_continuation( |
585 | write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence, |
586 | CompletionCondition, WriteHandler>* this_handler) |
587 | { |
588 | return this_handler->start_ == 0 ? true |
589 | : boost_asio_handler_cont_helpers::is_continuation( |
590 | this_handler->handler_); |
591 | } |
592 | |
593 | template <typename Function, typename AsyncRandomAccessWriteDevice, |
594 | typename ConstBufferSequence, typename CompletionCondition, |
595 | typename WriteHandler> |
596 | inline void asio_handler_invoke(Function& function, |
597 | write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence, |
598 | CompletionCondition, WriteHandler>* this_handler) |
599 | { |
600 | boost_asio_handler_invoke_helpers::invoke( |
601 | function, this_handler->handler_); |
602 | } |
603 | |
604 | template <typename Function, typename AsyncRandomAccessWriteDevice, |
605 | typename ConstBufferSequence, typename CompletionCondition, |
606 | typename WriteHandler> |
607 | inline void asio_handler_invoke(const Function& function, |
608 | write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence, |
609 | CompletionCondition, WriteHandler>* this_handler) |
610 | { |
611 | boost_asio_handler_invoke_helpers::invoke( |
612 | function, this_handler->handler_); |
613 | } |
614 | |
615 | template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence, |
616 | typename CompletionCondition, typename WriteHandler> |
617 | inline write_at_op<AsyncRandomAccessWriteDevice, |
618 | ConstBufferSequence, CompletionCondition, WriteHandler> |
619 | make_write_at_op(AsyncRandomAccessWriteDevice& d, |
620 | uint64_t offset, const ConstBufferSequence& buffers, |
621 | CompletionCondition completion_condition, WriteHandler handler) |
622 | { |
623 | return write_at_op<AsyncRandomAccessWriteDevice, |
624 | ConstBufferSequence, CompletionCondition, WriteHandler>( |
625 | d, offset, buffers, completion_condition, handler); |
626 | } |
627 | } // namespace detail |
628 | |
629 | template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence, |
630 | typename CompletionCondition, typename WriteHandler> |
631 | inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, |
632 | void (boost::system::error_code, std::size_t)) |
633 | async_write_at(AsyncRandomAccessWriteDevice& d, |
634 | uint64_t offset, const ConstBufferSequence& buffers, |
635 | CompletionCondition completion_condition, |
636 | BOOST_ASIO_MOVE_ARG(WriteHandler) handler) |
637 | { |
638 | // If you get an error on the following line it means that your handler does |
639 | // not meet the documented type requirements for a WriteHandler. |
640 | BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; |
641 | |
642 | detail::async_result_init< |
643 | WriteHandler, void (boost::system::error_code, std::size_t)> init( |
644 | BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); |
645 | |
646 | detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence, |
647 | CompletionCondition, BOOST_ASIO_HANDLER_TYPE( |
648 | WriteHandler, void (boost::system::error_code, std::size_t))>( |
649 | d, offset, buffers, completion_condition, init.handler)( |
650 | boost::system::error_code(), 0, 1); |
651 | |
652 | return init.result.get(); |
653 | } |
654 | |
655 | template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence, |
656 | typename WriteHandler> |
657 | inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, |
658 | void (boost::system::error_code, std::size_t)) |
659 | async_write_at(AsyncRandomAccessWriteDevice& d, |
660 | uint64_t offset, const ConstBufferSequence& buffers, |
661 | BOOST_ASIO_MOVE_ARG(WriteHandler) handler) |
662 | { |
663 | // If you get an error on the following line it means that your handler does |
664 | // not meet the documented type requirements for a WriteHandler. |
665 | BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; |
666 | |
667 | detail::async_result_init< |
668 | WriteHandler, void (boost::system::error_code, std::size_t)> init( |
669 | BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); |
670 | |
671 | detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence, |
672 | detail::transfer_all_t, BOOST_ASIO_HANDLER_TYPE( |
673 | WriteHandler, void (boost::system::error_code, std::size_t))>( |
674 | d, offset, buffers, transfer_all(), init.handler)( |
675 | boost::system::error_code(), 0, 1); |
676 | |
677 | return init.result.get(); |
678 | } |
679 | |
680 | #if !defined(BOOST_ASIO_NO_IOSTREAM) |
681 | |
682 | namespace detail |
683 | { |
684 | template <typename Allocator, typename WriteHandler> |
685 | class write_at_streambuf_op |
686 | { |
687 | public: |
688 | write_at_streambuf_op( |
689 | boost::asio::basic_streambuf<Allocator>& streambuf, |
690 | WriteHandler& handler) |
691 | : streambuf_(streambuf), |
692 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)) |
693 | { |
694 | } |
695 | |
696 | #if defined(BOOST_ASIO_HAS_MOVE) |
697 | write_at_streambuf_op(const write_at_streambuf_op& other) |
698 | : streambuf_(other.streambuf_), |
699 | handler_(other.handler_) |
700 | { |
701 | } |
702 | |
703 | write_at_streambuf_op(write_at_streambuf_op&& other) |
704 | : streambuf_(other.streambuf_), |
705 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_)) |
706 | { |
707 | } |
708 | #endif // defined(BOOST_ASIO_HAS_MOVE) |
709 | |
710 | void operator()(const boost::system::error_code& ec, |
711 | const std::size_t bytes_transferred) |
712 | { |
713 | streambuf_.consume(bytes_transferred); |
714 | handler_(ec, bytes_transferred); |
715 | } |
716 | |
717 | //private: |
718 | boost::asio::basic_streambuf<Allocator>& streambuf_; |
719 | WriteHandler handler_; |
720 | }; |
721 | |
722 | template <typename Allocator, typename WriteHandler> |
723 | inline void* asio_handler_allocate(std::size_t size, |
724 | write_at_streambuf_op<Allocator, WriteHandler>* this_handler) |
725 | { |
726 | return boost_asio_handler_alloc_helpers::allocate( |
727 | size, this_handler->handler_); |
728 | } |
729 | |
730 | template <typename Allocator, typename WriteHandler> |
731 | inline void asio_handler_deallocate(void* pointer, std::size_t size, |
732 | write_at_streambuf_op<Allocator, WriteHandler>* this_handler) |
733 | { |
734 | boost_asio_handler_alloc_helpers::deallocate( |
735 | pointer, size, this_handler->handler_); |
736 | } |
737 | |
738 | template <typename Allocator, typename WriteHandler> |
739 | inline bool asio_handler_is_continuation( |
740 | write_at_streambuf_op<Allocator, WriteHandler>* this_handler) |
741 | { |
742 | return boost_asio_handler_cont_helpers::is_continuation( |
743 | this_handler->handler_); |
744 | } |
745 | |
746 | template <typename Function, typename Allocator, typename WriteHandler> |
747 | inline void asio_handler_invoke(Function& function, |
748 | write_at_streambuf_op<Allocator, WriteHandler>* this_handler) |
749 | { |
750 | boost_asio_handler_invoke_helpers::invoke( |
751 | function, this_handler->handler_); |
752 | } |
753 | |
754 | template <typename Function, typename Allocator, typename WriteHandler> |
755 | inline void asio_handler_invoke(const Function& function, |
756 | write_at_streambuf_op<Allocator, WriteHandler>* this_handler) |
757 | { |
758 | boost_asio_handler_invoke_helpers::invoke( |
759 | function, this_handler->handler_); |
760 | } |
761 | |
762 | template <typename Allocator, typename WriteHandler> |
763 | inline write_at_streambuf_op<Allocator, WriteHandler> |
764 | make_write_at_streambuf_op( |
765 | boost::asio::basic_streambuf<Allocator>& b, WriteHandler handler) |
766 | { |
767 | return write_at_streambuf_op<Allocator, WriteHandler>(b, handler); |
768 | } |
769 | } // namespace detail |
770 | |
771 | template <typename AsyncRandomAccessWriteDevice, typename Allocator, |
772 | typename CompletionCondition, typename WriteHandler> |
773 | inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, |
774 | void (boost::system::error_code, std::size_t)) |
775 | async_write_at(AsyncRandomAccessWriteDevice& d, |
776 | uint64_t offset, boost::asio::basic_streambuf<Allocator>& b, |
777 | CompletionCondition completion_condition, |
778 | BOOST_ASIO_MOVE_ARG(WriteHandler) handler) |
779 | { |
780 | // If you get an error on the following line it means that your handler does |
781 | // not meet the documented type requirements for a WriteHandler. |
782 | BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; |
783 | |
784 | detail::async_result_init< |
785 | WriteHandler, void (boost::system::error_code, std::size_t)> init( |
786 | BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); |
787 | |
788 | async_write_at(d, offset, b.data(), completion_condition, |
789 | detail::write_at_streambuf_op<Allocator, BOOST_ASIO_HANDLER_TYPE( |
790 | WriteHandler, void (boost::system::error_code, std::size_t))>( |
791 | b, init.handler)); |
792 | |
793 | return init.result.get(); |
794 | } |
795 | |
796 | template <typename AsyncRandomAccessWriteDevice, typename Allocator, |
797 | typename WriteHandler> |
798 | inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, |
799 | void (boost::system::error_code, std::size_t)) |
800 | async_write_at(AsyncRandomAccessWriteDevice& d, |
801 | uint64_t offset, boost::asio::basic_streambuf<Allocator>& b, |
802 | BOOST_ASIO_MOVE_ARG(WriteHandler) handler) |
803 | { |
804 | // If you get an error on the following line it means that your handler does |
805 | // not meet the documented type requirements for a WriteHandler. |
806 | BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; |
807 | |
808 | detail::async_result_init< |
809 | WriteHandler, void (boost::system::error_code, std::size_t)> init( |
810 | BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); |
811 | |
812 | async_write_at(d, offset, b.data(), transfer_all(), |
813 | detail::write_at_streambuf_op<Allocator, BOOST_ASIO_HANDLER_TYPE( |
814 | WriteHandler, void (boost::system::error_code, std::size_t))>( |
815 | b, init.handler)); |
816 | |
817 | return init.result.get(); |
818 | } |
819 | |
820 | #endif // !defined(BOOST_ASIO_NO_IOSTREAM) |
821 | |
822 | } // namespace asio |
823 | } // namespace boost |
824 | |
825 | #include <boost/asio/detail/pop_options.hpp> |
826 | |
827 | #endif // BOOST_ASIO_IMPL_WRITE_AT_HPP |
828 | |