]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // impl/write_at.hpp | |
3 | // ~~~~~~~~~~~~~~~~~ | |
4 | // | |
5 | // Copyright (c) 2003-2016 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 |