write_at.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. //
  2. // impl/write_at.hpp
  3. // ~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2011 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. #ifndef ASIO_IMPL_WRITE_AT_HPP
  11. #define ASIO_IMPL_WRITE_AT_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/buffer.hpp"
  16. #include "asio/completion_condition.hpp"
  17. #include "asio/detail/base_from_completion_cond.hpp"
  18. #include "asio/detail/bind_handler.hpp"
  19. #include "asio/detail/consuming_buffers.hpp"
  20. #include "asio/detail/handler_alloc_helpers.hpp"
  21. #include "asio/detail/handler_invoke_helpers.hpp"
  22. #include "asio/detail/throw_error.hpp"
  23. #include "asio/detail/push_options.hpp"
  24. namespace asio {
  25. template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
  26. typename CompletionCondition>
  27. std::size_t write_at(SyncRandomAccessWriteDevice& d,
  28. boost::uint64_t offset, const ConstBufferSequence& buffers,
  29. CompletionCondition completion_condition, asio::error_code& ec)
  30. {
  31. ec = asio::error_code();
  32. asio::detail::consuming_buffers<
  33. const_buffer, ConstBufferSequence> tmp(buffers);
  34. std::size_t total_transferred = 0;
  35. tmp.prepare(detail::adapt_completion_condition_result(
  36. completion_condition(ec, total_transferred)));
  37. while (tmp.begin() != tmp.end())
  38. {
  39. std::size_t bytes_transferred = d.write_some_at(
  40. offset + total_transferred, tmp, ec);
  41. tmp.consume(bytes_transferred);
  42. total_transferred += bytes_transferred;
  43. tmp.prepare(detail::adapt_completion_condition_result(
  44. completion_condition(ec, total_transferred)));
  45. }
  46. return total_transferred;
  47. }
  48. template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>
  49. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  50. boost::uint64_t offset, const ConstBufferSequence& buffers)
  51. {
  52. asio::error_code ec;
  53. std::size_t bytes_transferred = write_at(
  54. d, offset, buffers, transfer_all(), ec);
  55. asio::detail::throw_error(ec);
  56. return bytes_transferred;
  57. }
  58. template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
  59. typename CompletionCondition>
  60. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  61. boost::uint64_t offset, const ConstBufferSequence& buffers,
  62. CompletionCondition completion_condition)
  63. {
  64. asio::error_code ec;
  65. std::size_t bytes_transferred = write_at(
  66. d, offset, buffers, completion_condition, ec);
  67. asio::detail::throw_error(ec);
  68. return bytes_transferred;
  69. }
  70. #if !defined(BOOST_NO_IOSTREAM)
  71. template <typename SyncRandomAccessWriteDevice, typename Allocator,
  72. typename CompletionCondition>
  73. std::size_t write_at(SyncRandomAccessWriteDevice& d,
  74. boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
  75. CompletionCondition completion_condition, asio::error_code& ec)
  76. {
  77. std::size_t bytes_transferred = write_at(
  78. d, offset, b.data(), completion_condition, ec);
  79. b.consume(bytes_transferred);
  80. return bytes_transferred;
  81. }
  82. template <typename SyncRandomAccessWriteDevice, typename Allocator>
  83. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  84. boost::uint64_t offset, asio::basic_streambuf<Allocator>& b)
  85. {
  86. asio::error_code ec;
  87. std::size_t bytes_transferred = write_at(d, offset, b, transfer_all(), ec);
  88. asio::detail::throw_error(ec);
  89. return bytes_transferred;
  90. }
  91. template <typename SyncRandomAccessWriteDevice, typename Allocator,
  92. typename CompletionCondition>
  93. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  94. boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
  95. CompletionCondition completion_condition)
  96. {
  97. asio::error_code ec;
  98. std::size_t bytes_transferred = write_at(
  99. d, offset, b, completion_condition, ec);
  100. asio::detail::throw_error(ec);
  101. return bytes_transferred;
  102. }
  103. #endif // !defined(BOOST_NO_IOSTREAM)
  104. namespace detail
  105. {
  106. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  107. typename CompletionCondition, typename WriteHandler>
  108. class write_at_op
  109. : detail::base_from_completion_cond<CompletionCondition>
  110. {
  111. public:
  112. write_at_op(AsyncRandomAccessWriteDevice& device,
  113. boost::uint64_t offset, const ConstBufferSequence& buffers,
  114. CompletionCondition completion_condition, WriteHandler handler)
  115. : detail::base_from_completion_cond<
  116. CompletionCondition>(completion_condition),
  117. device_(device),
  118. offset_(offset),
  119. buffers_(buffers),
  120. total_transferred_(0),
  121. handler_(handler)
  122. {
  123. }
  124. void operator()(const asio::error_code& ec,
  125. std::size_t bytes_transferred, int start = 0)
  126. {
  127. switch (start)
  128. {
  129. case 1:
  130. buffers_.prepare(this->check_for_completion(ec, total_transferred_));
  131. for (;;)
  132. {
  133. device_.async_write_some_at(
  134. offset_ + total_transferred_, buffers_, *this);
  135. return; default:
  136. total_transferred_ += bytes_transferred;
  137. buffers_.consume(bytes_transferred);
  138. buffers_.prepare(this->check_for_completion(ec, total_transferred_));
  139. if ((!ec && bytes_transferred == 0)
  140. || buffers_.begin() == buffers_.end())
  141. break;
  142. }
  143. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  144. }
  145. }
  146. //private:
  147. AsyncRandomAccessWriteDevice& device_;
  148. boost::uint64_t offset_;
  149. asio::detail::consuming_buffers<
  150. const_buffer, ConstBufferSequence> buffers_;
  151. std::size_t total_transferred_;
  152. WriteHandler handler_;
  153. };
  154. template <typename AsyncRandomAccessWriteDevice,
  155. typename CompletionCondition, typename WriteHandler>
  156. class write_at_op<AsyncRandomAccessWriteDevice,
  157. asio::mutable_buffers_1, CompletionCondition, WriteHandler>
  158. : detail::base_from_completion_cond<CompletionCondition>
  159. {
  160. public:
  161. write_at_op(AsyncRandomAccessWriteDevice& device,
  162. boost::uint64_t offset, const asio::mutable_buffers_1& buffers,
  163. CompletionCondition completion_condition,
  164. WriteHandler handler)
  165. : detail::base_from_completion_cond<
  166. CompletionCondition>(completion_condition),
  167. device_(device),
  168. offset_(offset),
  169. buffer_(buffers),
  170. total_transferred_(0),
  171. handler_(handler)
  172. {
  173. }
  174. void operator()(const asio::error_code& ec,
  175. std::size_t bytes_transferred, int start = 0)
  176. {
  177. std::size_t n = 0;
  178. switch (start)
  179. {
  180. case 1:
  181. n = this->check_for_completion(ec, total_transferred_);
  182. for (;;)
  183. {
  184. device_.async_write_some_at(offset_ + total_transferred_,
  185. asio::buffer(buffer_ + total_transferred_, n), *this);
  186. return; default:
  187. total_transferred_ += bytes_transferred;
  188. if ((!ec && bytes_transferred == 0)
  189. || (n = this->check_for_completion(ec, total_transferred_)) == 0
  190. || total_transferred_ == asio::buffer_size(buffer_))
  191. break;
  192. }
  193. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  194. }
  195. }
  196. //private:
  197. AsyncRandomAccessWriteDevice& device_;
  198. boost::uint64_t offset_;
  199. asio::mutable_buffer buffer_;
  200. std::size_t total_transferred_;
  201. WriteHandler handler_;
  202. };
  203. template <typename AsyncRandomAccessWriteDevice,
  204. typename CompletionCondition, typename WriteHandler>
  205. class write_at_op<AsyncRandomAccessWriteDevice, asio::const_buffers_1,
  206. CompletionCondition, WriteHandler>
  207. : detail::base_from_completion_cond<CompletionCondition>
  208. {
  209. public:
  210. write_at_op(AsyncRandomAccessWriteDevice& device,
  211. boost::uint64_t offset, const asio::const_buffers_1& buffers,
  212. CompletionCondition completion_condition,
  213. WriteHandler handler)
  214. : detail::base_from_completion_cond<
  215. CompletionCondition>(completion_condition),
  216. device_(device),
  217. offset_(offset),
  218. buffer_(buffers),
  219. total_transferred_(0),
  220. handler_(handler)
  221. {
  222. }
  223. void operator()(const asio::error_code& ec,
  224. std::size_t bytes_transferred, int start = 0)
  225. {
  226. std::size_t n = 0;
  227. switch (start)
  228. {
  229. case 1:
  230. n = this->check_for_completion(ec, total_transferred_);
  231. for (;;)
  232. {
  233. device_.async_write_some_at(offset_ + total_transferred_,
  234. asio::buffer(buffer_ + total_transferred_, n), *this);
  235. return; default:
  236. total_transferred_ += bytes_transferred;
  237. if ((!ec && bytes_transferred == 0)
  238. || (n = this->check_for_completion(ec, total_transferred_)) == 0
  239. || total_transferred_ == asio::buffer_size(buffer_))
  240. break;
  241. }
  242. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  243. }
  244. }
  245. //private:
  246. AsyncRandomAccessWriteDevice& device_;
  247. boost::uint64_t offset_;
  248. asio::const_buffer buffer_;
  249. std::size_t total_transferred_;
  250. WriteHandler handler_;
  251. };
  252. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  253. typename CompletionCondition, typename WriteHandler>
  254. inline void* asio_handler_allocate(std::size_t size,
  255. write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  256. CompletionCondition, WriteHandler>* this_handler)
  257. {
  258. return asio_handler_alloc_helpers::allocate(
  259. size, this_handler->handler_);
  260. }
  261. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  262. typename CompletionCondition, typename WriteHandler>
  263. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  264. write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  265. CompletionCondition, WriteHandler>* this_handler)
  266. {
  267. asio_handler_alloc_helpers::deallocate(
  268. pointer, size, this_handler->handler_);
  269. }
  270. template <typename Function, typename AsyncRandomAccessWriteDevice,
  271. typename ConstBufferSequence, typename CompletionCondition,
  272. typename WriteHandler>
  273. inline void asio_handler_invoke(const Function& function,
  274. write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  275. CompletionCondition, WriteHandler>* this_handler)
  276. {
  277. asio_handler_invoke_helpers::invoke(
  278. function, this_handler->handler_);
  279. }
  280. } // namespace detail
  281. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  282. typename CompletionCondition, typename WriteHandler>
  283. inline void async_write_at(AsyncRandomAccessWriteDevice& d,
  284. boost::uint64_t offset, const ConstBufferSequence& buffers,
  285. CompletionCondition completion_condition, WriteHandler handler)
  286. {
  287. detail::write_at_op<AsyncRandomAccessWriteDevice,
  288. ConstBufferSequence, CompletionCondition, WriteHandler>(
  289. d, offset, buffers, completion_condition, handler)(
  290. asio::error_code(), 0, 1);
  291. }
  292. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  293. typename WriteHandler>
  294. inline void async_write_at(AsyncRandomAccessWriteDevice& d,
  295. boost::uint64_t offset, const ConstBufferSequence& buffers,
  296. WriteHandler handler)
  297. {
  298. async_write_at(d, offset, buffers, transfer_all(), handler);
  299. }
  300. #if !defined(BOOST_NO_IOSTREAM)
  301. namespace detail
  302. {
  303. template <typename AsyncRandomAccessWriteDevice,
  304. typename Allocator, typename WriteHandler>
  305. class write_at_streambuf_op
  306. {
  307. public:
  308. write_at_streambuf_op(
  309. asio::basic_streambuf<Allocator>& streambuf,
  310. WriteHandler handler)
  311. : streambuf_(streambuf),
  312. handler_(handler)
  313. {
  314. }
  315. void operator()(const asio::error_code& ec,
  316. const std::size_t bytes_transferred)
  317. {
  318. streambuf_.consume(bytes_transferred);
  319. handler_(ec, bytes_transferred);
  320. }
  321. //private:
  322. asio::basic_streambuf<Allocator>& streambuf_;
  323. WriteHandler handler_;
  324. };
  325. template <typename AsyncRandomAccessWriteDevice, typename Allocator,
  326. typename WriteHandler>
  327. inline void* asio_handler_allocate(std::size_t size,
  328. write_at_streambuf_op<AsyncRandomAccessWriteDevice,
  329. Allocator, WriteHandler>* this_handler)
  330. {
  331. return asio_handler_alloc_helpers::allocate(
  332. size, this_handler->handler_);
  333. }
  334. template <typename AsyncRandomAccessWriteDevice, typename Allocator,
  335. typename WriteHandler>
  336. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  337. write_at_streambuf_op<AsyncRandomAccessWriteDevice,
  338. Allocator, WriteHandler>* this_handler)
  339. {
  340. asio_handler_alloc_helpers::deallocate(
  341. pointer, size, this_handler->handler_);
  342. }
  343. template <typename Function, typename AsyncRandomAccessWriteDevice,
  344. typename Allocator, typename WriteHandler>
  345. inline void asio_handler_invoke(const Function& function,
  346. write_at_streambuf_op<AsyncRandomAccessWriteDevice,
  347. Allocator, WriteHandler>* this_handler)
  348. {
  349. asio_handler_invoke_helpers::invoke(
  350. function, this_handler->handler_);
  351. }
  352. } // namespace detail
  353. template <typename AsyncRandomAccessWriteDevice, typename Allocator,
  354. typename CompletionCondition, typename WriteHandler>
  355. inline void async_write_at(AsyncRandomAccessWriteDevice& d,
  356. boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
  357. CompletionCondition completion_condition, WriteHandler handler)
  358. {
  359. async_write_at(d, offset, b.data(), completion_condition,
  360. detail::write_at_streambuf_op<
  361. AsyncRandomAccessWriteDevice, Allocator, WriteHandler>(b, handler));
  362. }
  363. template <typename AsyncRandomAccessWriteDevice, typename Allocator,
  364. typename WriteHandler>
  365. inline void async_write_at(AsyncRandomAccessWriteDevice& d,
  366. boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
  367. WriteHandler handler)
  368. {
  369. async_write_at(d, offset, b, transfer_all(), handler);
  370. }
  371. #endif // !defined(BOOST_NO_IOSTREAM)
  372. } // namespace asio
  373. #include "asio/detail/pop_options.hpp"
  374. #endif // ASIO_IMPL_WRITE_AT_HPP