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
33namespace boost {
34namespace asio {
35
36template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
37 typename CompletionCondition>
38std::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
60template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>
61inline 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
71template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>
72inline 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
79template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
80 typename CompletionCondition>
81inline 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
94template <typename SyncRandomAccessWriteDevice, typename Allocator,
95 typename CompletionCondition>
96std::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
106template <typename SyncRandomAccessWriteDevice, typename Allocator>
107inline 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
116template <typename SyncRandomAccessWriteDevice, typename Allocator>
117inline 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
124template <typename SyncRandomAccessWriteDevice, typename Allocator,
125 typename CompletionCondition>
126inline 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
139namespace 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
629template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
630 typename CompletionCondition, typename WriteHandler>
631inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
632 void (boost::system::error_code, std::size_t))
633async_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
655template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
656 typename WriteHandler>
657inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
658 void (boost::system::error_code, std::size_t))
659async_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
682namespace 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
771template <typename AsyncRandomAccessWriteDevice, typename Allocator,
772 typename CompletionCondition, typename WriteHandler>
773inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
774 void (boost::system::error_code, std::size_t))
775async_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
796template <typename AsyncRandomAccessWriteDevice, typename Allocator,
797 typename WriteHandler>
798inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
799 void (boost::system::error_code, std::size_t))
800async_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