write_at.ipp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. //
  2. // write_at.ipp
  3. // ~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2008 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 BOOST_ASIO_WRITE_AT_IPP
  11. #define BOOST_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 <boost/asio/detail/push_options.hpp>
  16. #include <boost/asio/buffer.hpp>
  17. #include <boost/asio/completion_condition.hpp>
  18. #include <boost/asio/detail/bind_handler.hpp>
  19. #include <boost/asio/detail/consuming_buffers.hpp>
  20. #include <boost/asio/detail/handler_alloc_helpers.hpp>
  21. #include <boost/asio/detail/handler_invoke_helpers.hpp>
  22. #include <boost/asio/detail/throw_error.hpp>
  23. namespace boost {
  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, boost::system::error_code& ec)
  30. {
  31. ec = boost::system::error_code();
  32. boost::asio::detail::consuming_buffers<
  33. const_buffer, ConstBufferSequence> tmp(buffers);
  34. std::size_t total_transferred = 0;
  35. tmp.set_max_size(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.set_max_size(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. boost::system::error_code ec;
  53. std::size_t bytes_transferred = write_at(
  54. d, offset, buffers, transfer_all(), ec);
  55. boost::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. boost::system::error_code ec;
  65. std::size_t bytes_transferred = write_at(
  66. d, offset, buffers, completion_condition, ec);
  67. boost::asio::detail::throw_error(ec);
  68. return bytes_transferred;
  69. }
  70. template <typename SyncRandomAccessWriteDevice, typename Allocator,
  71. typename CompletionCondition>
  72. std::size_t write_at(SyncRandomAccessWriteDevice& d,
  73. boost::uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  74. CompletionCondition completion_condition, boost::system::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, boost::asio::basic_streambuf<Allocator>& b)
  84. {
  85. boost::system::error_code ec;
  86. std::size_t bytes_transferred = write_at(d, offset, b, transfer_all(), ec);
  87. boost::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, boost::asio::basic_streambuf<Allocator>& b,
  94. CompletionCondition completion_condition)
  95. {
  96. boost::system::error_code ec;
  97. std::size_t bytes_transferred = write_at(
  98. d, offset, b, completion_condition, ec);
  99. boost::asio::detail::throw_error(ec);
  100. return bytes_transferred;
  101. }
  102. namespace detail
  103. {
  104. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  105. typename CompletionCondition, typename WriteHandler>
  106. class write_at_handler
  107. {
  108. public:
  109. typedef boost::asio::detail::consuming_buffers<
  110. const_buffer, ConstBufferSequence> buffers_type;
  111. write_at_handler(AsyncRandomAccessWriteDevice& stream,
  112. boost::uint64_t offset, const buffers_type& buffers,
  113. CompletionCondition completion_condition, WriteHandler handler)
  114. : stream_(stream),
  115. buffers_(buffers),
  116. offset_(offset),
  117. total_transferred_(0),
  118. completion_condition_(completion_condition),
  119. handler_(handler)
  120. {
  121. }
  122. void operator()(const boost::system::error_code& ec,
  123. std::size_t bytes_transferred)
  124. {
  125. total_transferred_ += bytes_transferred;
  126. buffers_.consume(bytes_transferred);
  127. buffers_.set_max_size(detail::adapt_completion_condition_result(
  128. completion_condition_(ec, total_transferred_)));
  129. if (buffers_.begin() == buffers_.end())
  130. {
  131. handler_(ec, total_transferred_);
  132. }
  133. else
  134. {
  135. stream_.async_write_some_at(
  136. offset_ + total_transferred_, buffers_, *this);
  137. }
  138. }
  139. //private:
  140. AsyncRandomAccessWriteDevice& stream_;
  141. buffers_type buffers_;
  142. boost::uint64_t offset_;
  143. std::size_t total_transferred_;
  144. CompletionCondition completion_condition_;
  145. WriteHandler handler_;
  146. };
  147. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  148. typename CompletionCondition, typename WriteHandler>
  149. inline void* asio_handler_allocate(std::size_t size,
  150. write_at_handler<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  151. CompletionCondition, WriteHandler>* this_handler)
  152. {
  153. return boost_asio_handler_alloc_helpers::allocate(
  154. size, &this_handler->handler_);
  155. }
  156. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  157. typename CompletionCondition, typename WriteHandler>
  158. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  159. write_at_handler<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  160. CompletionCondition, WriteHandler>* this_handler)
  161. {
  162. boost_asio_handler_alloc_helpers::deallocate(
  163. pointer, size, &this_handler->handler_);
  164. }
  165. template <typename Function, typename AsyncRandomAccessWriteDevice,
  166. typename ConstBufferSequence, typename CompletionCondition,
  167. typename WriteHandler>
  168. inline void asio_handler_invoke(const Function& function,
  169. write_at_handler<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  170. CompletionCondition, WriteHandler>* this_handler)
  171. {
  172. boost_asio_handler_invoke_helpers::invoke(
  173. function, &this_handler->handler_);
  174. }
  175. } // namespace detail
  176. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  177. typename CompletionCondition, typename WriteHandler>
  178. inline void async_write_at(AsyncRandomAccessWriteDevice& d,
  179. boost::uint64_t offset, const ConstBufferSequence& buffers,
  180. CompletionCondition completion_condition, WriteHandler handler)
  181. {
  182. boost::asio::detail::consuming_buffers<
  183. const_buffer, ConstBufferSequence> tmp(buffers);
  184. boost::system::error_code ec;
  185. std::size_t total_transferred = 0;
  186. tmp.set_max_size(detail::adapt_completion_condition_result(
  187. completion_condition(ec, total_transferred)));
  188. if (tmp.begin() == tmp.end())
  189. {
  190. d.get_io_service().post(detail::bind_handler(
  191. handler, ec, total_transferred));
  192. return;
  193. }
  194. d.async_write_some_at(offset, tmp,
  195. detail::write_at_handler<AsyncRandomAccessWriteDevice,
  196. ConstBufferSequence, CompletionCondition, WriteHandler>(
  197. d, offset, tmp, completion_condition, handler));
  198. }
  199. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  200. typename WriteHandler>
  201. inline void async_write_at(AsyncRandomAccessWriteDevice& d,
  202. boost::uint64_t offset, const ConstBufferSequence& buffers,
  203. WriteHandler handler)
  204. {
  205. async_write_at(d, offset, buffers, transfer_all(), handler);
  206. }
  207. namespace detail
  208. {
  209. template <typename AsyncRandomAccessWriteDevice, typename Allocator,
  210. typename WriteHandler>
  211. class write_at_streambuf_handler
  212. {
  213. public:
  214. write_at_streambuf_handler(
  215. boost::asio::basic_streambuf<Allocator>& streambuf,
  216. WriteHandler handler)
  217. : streambuf_(streambuf),
  218. handler_(handler)
  219. {
  220. }
  221. void operator()(const boost::system::error_code& ec,
  222. std::size_t bytes_transferred)
  223. {
  224. streambuf_.consume(bytes_transferred);
  225. handler_(ec, bytes_transferred);
  226. }
  227. //private:
  228. boost::asio::basic_streambuf<Allocator>& streambuf_;
  229. WriteHandler handler_;
  230. };
  231. template <typename AsyncRandomAccessWriteDevice, typename Allocator,
  232. typename WriteHandler>
  233. inline void* asio_handler_allocate(std::size_t size,
  234. write_at_streambuf_handler<AsyncRandomAccessWriteDevice,
  235. Allocator, WriteHandler>* this_handler)
  236. {
  237. return boost_asio_handler_alloc_helpers::allocate(
  238. size, &this_handler->handler_);
  239. }
  240. template <typename AsyncRandomAccessWriteDevice, typename Allocator,
  241. typename WriteHandler>
  242. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  243. write_at_streambuf_handler<AsyncRandomAccessWriteDevice,
  244. Allocator, WriteHandler>* this_handler)
  245. {
  246. boost_asio_handler_alloc_helpers::deallocate(
  247. pointer, size, &this_handler->handler_);
  248. }
  249. template <typename Function, typename AsyncRandomAccessWriteDevice,
  250. typename Allocator, typename WriteHandler>
  251. inline void asio_handler_invoke(const Function& function,
  252. write_at_streambuf_handler<AsyncRandomAccessWriteDevice,
  253. Allocator, WriteHandler>* this_handler)
  254. {
  255. boost_asio_handler_invoke_helpers::invoke(
  256. function, &this_handler->handler_);
  257. }
  258. } // namespace detail
  259. template <typename AsyncRandomAccessWriteDevice, typename Allocator,
  260. typename CompletionCondition, typename WriteHandler>
  261. inline void async_write_at(AsyncRandomAccessWriteDevice& d,
  262. boost::uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  263. CompletionCondition completion_condition, WriteHandler handler)
  264. {
  265. async_write_at(d, offset, b.data(), completion_condition,
  266. detail::write_at_streambuf_handler<
  267. AsyncRandomAccessWriteDevice, Allocator, WriteHandler>(b, handler));
  268. }
  269. template <typename AsyncRandomAccessWriteDevice, typename Allocator,
  270. typename WriteHandler>
  271. inline void async_write_at(AsyncRandomAccessWriteDevice& d,
  272. boost::uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  273. WriteHandler handler)
  274. {
  275. async_write_at(d, offset, b, transfer_all(), handler);
  276. }
  277. } // namespace asio
  278. } // namespace boost
  279. #include <boost/asio/detail/pop_options.hpp>
  280. #endif // BOOST_ASIO_WRITE_AT_IPP