write_at.ipp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. //
  2. // write_at.ipp
  3. // ~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2010 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_WRITE_AT_IPP
  11. #define ASIO_WRITE_AT_IPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/detail/push_options.hpp"
  16. #include "asio/buffer.hpp"
  17. #include "asio/completion_condition.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. namespace asio {
  24. template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
  25. typename CompletionCondition>
  26. std::size_t write_at(SyncRandomAccessWriteDevice& d,
  27. boost::uint64_t offset, const ConstBufferSequence& buffers,
  28. CompletionCondition completion_condition, asio::error_code& ec)
  29. {
  30. ec = asio::error_code();
  31. asio::detail::consuming_buffers<
  32. const_buffer, ConstBufferSequence> tmp(buffers);
  33. std::size_t total_transferred = 0;
  34. tmp.prepare(detail::adapt_completion_condition_result(
  35. completion_condition(ec, total_transferred)));
  36. while (tmp.begin() != tmp.end())
  37. {
  38. std::size_t bytes_transferred = d.write_some_at(
  39. offset + total_transferred, tmp, ec);
  40. tmp.consume(bytes_transferred);
  41. total_transferred += bytes_transferred;
  42. tmp.prepare(detail::adapt_completion_condition_result(
  43. completion_condition(ec, total_transferred)));
  44. }
  45. return total_transferred;
  46. }
  47. template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>
  48. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  49. boost::uint64_t offset, const ConstBufferSequence& buffers)
  50. {
  51. asio::error_code ec;
  52. std::size_t bytes_transferred = write_at(
  53. d, offset, buffers, transfer_all(), ec);
  54. asio::detail::throw_error(ec);
  55. return bytes_transferred;
  56. }
  57. template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
  58. typename CompletionCondition>
  59. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  60. boost::uint64_t offset, const ConstBufferSequence& buffers,
  61. CompletionCondition completion_condition)
  62. {
  63. asio::error_code ec;
  64. std::size_t bytes_transferred = write_at(
  65. d, offset, buffers, completion_condition, ec);
  66. asio::detail::throw_error(ec);
  67. return bytes_transferred;
  68. }
  69. #if !defined(BOOST_NO_IOSTREAM)
  70. template <typename SyncRandomAccessWriteDevice, typename Allocator,
  71. typename CompletionCondition>
  72. std::size_t write_at(SyncRandomAccessWriteDevice& d,
  73. boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
  74. CompletionCondition completion_condition, asio::error_code& ec)
  75. {
  76. std::size_t bytes_transferred = write_at(
  77. d, offset, b.data(), completion_condition, ec);
  78. b.consume(bytes_transferred);
  79. return bytes_transferred;
  80. }
  81. template <typename SyncRandomAccessWriteDevice, typename Allocator>
  82. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  83. boost::uint64_t offset, asio::basic_streambuf<Allocator>& b)
  84. {
  85. asio::error_code ec;
  86. std::size_t bytes_transferred = write_at(d, offset, b, transfer_all(), ec);
  87. asio::detail::throw_error(ec);
  88. return bytes_transferred;
  89. }
  90. template <typename SyncRandomAccessWriteDevice, typename Allocator,
  91. typename CompletionCondition>
  92. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  93. boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
  94. CompletionCondition completion_condition)
  95. {
  96. asio::error_code ec;
  97. std::size_t bytes_transferred = write_at(
  98. d, offset, b, completion_condition, ec);
  99. asio::detail::throw_error(ec);
  100. return bytes_transferred;
  101. }
  102. #endif // !defined(BOOST_NO_IOSTREAM)
  103. namespace detail
  104. {
  105. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  106. typename CompletionCondition, typename WriteHandler>
  107. class write_at_handler
  108. {
  109. public:
  110. typedef asio::detail::consuming_buffers<
  111. const_buffer, ConstBufferSequence> buffers_type;
  112. write_at_handler(AsyncRandomAccessWriteDevice& stream,
  113. boost::uint64_t offset, const buffers_type& buffers,
  114. CompletionCondition completion_condition, WriteHandler handler)
  115. : stream_(stream),
  116. buffers_(buffers),
  117. offset_(offset),
  118. total_transferred_(0),
  119. completion_condition_(completion_condition),
  120. handler_(handler)
  121. {
  122. }
  123. void operator()(const asio::error_code& ec,
  124. std::size_t bytes_transferred)
  125. {
  126. total_transferred_ += bytes_transferred;
  127. buffers_.consume(bytes_transferred);
  128. buffers_.prepare(detail::adapt_completion_condition_result(
  129. completion_condition_(ec, total_transferred_)));
  130. if (buffers_.begin() == buffers_.end())
  131. {
  132. handler_(ec, total_transferred_);
  133. }
  134. else
  135. {
  136. stream_.async_write_some_at(
  137. offset_ + total_transferred_, buffers_, *this);
  138. }
  139. }
  140. //private:
  141. AsyncRandomAccessWriteDevice& stream_;
  142. buffers_type buffers_;
  143. boost::uint64_t offset_;
  144. std::size_t total_transferred_;
  145. CompletionCondition completion_condition_;
  146. WriteHandler handler_;
  147. };
  148. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  149. typename CompletionCondition, typename WriteHandler>
  150. inline void* asio_handler_allocate(std::size_t size,
  151. write_at_handler<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  152. CompletionCondition, WriteHandler>* this_handler)
  153. {
  154. return asio_handler_alloc_helpers::allocate(
  155. size, this_handler->handler_);
  156. }
  157. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  158. typename CompletionCondition, typename WriteHandler>
  159. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  160. write_at_handler<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  161. CompletionCondition, WriteHandler>* this_handler)
  162. {
  163. asio_handler_alloc_helpers::deallocate(
  164. pointer, size, this_handler->handler_);
  165. }
  166. template <typename Function, typename AsyncRandomAccessWriteDevice,
  167. typename ConstBufferSequence, typename CompletionCondition,
  168. typename WriteHandler>
  169. inline void asio_handler_invoke(const Function& function,
  170. write_at_handler<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  171. CompletionCondition, WriteHandler>* this_handler)
  172. {
  173. asio_handler_invoke_helpers::invoke(
  174. function, this_handler->handler_);
  175. }
  176. } // namespace detail
  177. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  178. typename CompletionCondition, typename WriteHandler>
  179. inline void async_write_at(AsyncRandomAccessWriteDevice& d,
  180. boost::uint64_t offset, const ConstBufferSequence& buffers,
  181. CompletionCondition completion_condition, WriteHandler handler)
  182. {
  183. asio::detail::consuming_buffers<
  184. const_buffer, ConstBufferSequence> tmp(buffers);
  185. asio::error_code ec;
  186. std::size_t total_transferred = 0;
  187. tmp.prepare(detail::adapt_completion_condition_result(
  188. completion_condition(ec, total_transferred)));
  189. if (tmp.begin() == tmp.end())
  190. {
  191. d.get_io_service().post(detail::bind_handler(
  192. handler, ec, total_transferred));
  193. return;
  194. }
  195. d.async_write_some_at(offset, tmp,
  196. detail::write_at_handler<AsyncRandomAccessWriteDevice,
  197. ConstBufferSequence, CompletionCondition, WriteHandler>(
  198. d, offset, tmp, completion_condition, handler));
  199. }
  200. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  201. typename WriteHandler>
  202. inline void async_write_at(AsyncRandomAccessWriteDevice& d,
  203. boost::uint64_t offset, const ConstBufferSequence& buffers,
  204. WriteHandler handler)
  205. {
  206. async_write_at(d, offset, buffers, transfer_all(), handler);
  207. }
  208. #if !defined(BOOST_NO_IOSTREAM)
  209. namespace detail
  210. {
  211. template <typename AsyncRandomAccessWriteDevice, typename Allocator,
  212. typename WriteHandler>
  213. class write_at_streambuf_handler
  214. {
  215. public:
  216. write_at_streambuf_handler(
  217. asio::basic_streambuf<Allocator>& streambuf,
  218. WriteHandler handler)
  219. : streambuf_(streambuf),
  220. handler_(handler)
  221. {
  222. }
  223. void operator()(const asio::error_code& ec,
  224. std::size_t bytes_transferred)
  225. {
  226. streambuf_.consume(bytes_transferred);
  227. handler_(ec, bytes_transferred);
  228. }
  229. //private:
  230. asio::basic_streambuf<Allocator>& streambuf_;
  231. WriteHandler handler_;
  232. };
  233. template <typename AsyncRandomAccessWriteDevice, typename Allocator,
  234. typename WriteHandler>
  235. inline void* asio_handler_allocate(std::size_t size,
  236. write_at_streambuf_handler<AsyncRandomAccessWriteDevice,
  237. Allocator, WriteHandler>* this_handler)
  238. {
  239. return asio_handler_alloc_helpers::allocate(
  240. size, this_handler->handler_);
  241. }
  242. template <typename AsyncRandomAccessWriteDevice, typename Allocator,
  243. typename WriteHandler>
  244. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  245. write_at_streambuf_handler<AsyncRandomAccessWriteDevice,
  246. Allocator, WriteHandler>* this_handler)
  247. {
  248. asio_handler_alloc_helpers::deallocate(
  249. pointer, size, this_handler->handler_);
  250. }
  251. template <typename Function, typename AsyncRandomAccessWriteDevice,
  252. typename Allocator, typename WriteHandler>
  253. inline void asio_handler_invoke(const Function& function,
  254. write_at_streambuf_handler<AsyncRandomAccessWriteDevice,
  255. Allocator, WriteHandler>* this_handler)
  256. {
  257. asio_handler_invoke_helpers::invoke(
  258. function, this_handler->handler_);
  259. }
  260. } // namespace detail
  261. template <typename AsyncRandomAccessWriteDevice, typename Allocator,
  262. typename CompletionCondition, typename WriteHandler>
  263. inline void async_write_at(AsyncRandomAccessWriteDevice& d,
  264. boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
  265. CompletionCondition completion_condition, WriteHandler handler)
  266. {
  267. async_write_at(d, offset, b.data(), completion_condition,
  268. detail::write_at_streambuf_handler<
  269. AsyncRandomAccessWriteDevice, Allocator, WriteHandler>(b, handler));
  270. }
  271. template <typename AsyncRandomAccessWriteDevice, typename Allocator,
  272. typename WriteHandler>
  273. inline void async_write_at(AsyncRandomAccessWriteDevice& d,
  274. boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
  275. WriteHandler handler)
  276. {
  277. async_write_at(d, offset, b, transfer_all(), handler);
  278. }
  279. #endif // !defined(BOOST_NO_IOSTREAM)
  280. } // namespace asio
  281. #include "asio/detail/pop_options.hpp"
  282. #endif // ASIO_WRITE_AT_IPP