buffered_read_stream.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. //
  2. // impl/buffered_read_stream.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. #ifndef ASIO_IMPL_BUFFERED_READ_STREAM_HPP
  11. #define ASIO_IMPL_BUFFERED_READ_STREAM_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/detail/handler_alloc_helpers.hpp"
  16. #include "asio/detail/handler_cont_helpers.hpp"
  17. #include "asio/detail/handler_invoke_helpers.hpp"
  18. #include "asio/detail/handler_type_requirements.hpp"
  19. #include "asio/detail/push_options.hpp"
  20. namespace asio {
  21. template <typename Stream>
  22. std::size_t buffered_read_stream<Stream>::fill()
  23. {
  24. detail::buffer_resize_guard<detail::buffered_stream_storage>
  25. resize_guard(storage_);
  26. std::size_t previous_size = storage_.size();
  27. storage_.resize(storage_.capacity());
  28. storage_.resize(previous_size + next_layer_.read_some(buffer(
  29. storage_.data() + previous_size,
  30. storage_.size() - previous_size)));
  31. resize_guard.commit();
  32. return storage_.size() - previous_size;
  33. }
  34. template <typename Stream>
  35. std::size_t buffered_read_stream<Stream>::fill(asio::error_code& ec)
  36. {
  37. detail::buffer_resize_guard<detail::buffered_stream_storage>
  38. resize_guard(storage_);
  39. std::size_t previous_size = storage_.size();
  40. storage_.resize(storage_.capacity());
  41. storage_.resize(previous_size + next_layer_.read_some(buffer(
  42. storage_.data() + previous_size,
  43. storage_.size() - previous_size),
  44. ec));
  45. resize_guard.commit();
  46. return storage_.size() - previous_size;
  47. }
  48. namespace detail
  49. {
  50. template <typename ReadHandler>
  51. class buffered_fill_handler
  52. {
  53. public:
  54. buffered_fill_handler(detail::buffered_stream_storage& storage,
  55. std::size_t previous_size, ReadHandler& handler)
  56. : storage_(storage),
  57. previous_size_(previous_size),
  58. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  59. {
  60. }
  61. #if defined(ASIO_HAS_MOVE)
  62. buffered_fill_handler(const buffered_fill_handler& other)
  63. : storage_(other.storage_),
  64. previous_size_(other.previous_size_),
  65. handler_(other.handler_)
  66. {
  67. }
  68. buffered_fill_handler(buffered_fill_handler&& other)
  69. : storage_(other.storage_),
  70. previous_size_(other.previous_size_),
  71. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  72. {
  73. }
  74. #endif // defined(ASIO_HAS_MOVE)
  75. void operator()(const asio::error_code& ec,
  76. const std::size_t bytes_transferred)
  77. {
  78. storage_.resize(previous_size_ + bytes_transferred);
  79. handler_(ec, bytes_transferred);
  80. }
  81. //private:
  82. detail::buffered_stream_storage& storage_;
  83. std::size_t previous_size_;
  84. ReadHandler handler_;
  85. };
  86. template <typename ReadHandler>
  87. inline void* asio_handler_allocate(std::size_t size,
  88. buffered_fill_handler<ReadHandler>* this_handler)
  89. {
  90. return asio_handler_alloc_helpers::allocate(
  91. size, this_handler->handler_);
  92. }
  93. template <typename ReadHandler>
  94. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  95. buffered_fill_handler<ReadHandler>* this_handler)
  96. {
  97. asio_handler_alloc_helpers::deallocate(
  98. pointer, size, this_handler->handler_);
  99. }
  100. template <typename ReadHandler>
  101. inline bool asio_handler_is_continuation(
  102. buffered_fill_handler<ReadHandler>* this_handler)
  103. {
  104. return asio_handler_cont_helpers::is_continuation(
  105. this_handler->handler_);
  106. }
  107. template <typename Function, typename ReadHandler>
  108. inline void asio_handler_invoke(Function& function,
  109. buffered_fill_handler<ReadHandler>* this_handler)
  110. {
  111. asio_handler_invoke_helpers::invoke(
  112. function, this_handler->handler_);
  113. }
  114. template <typename Function, typename ReadHandler>
  115. inline void asio_handler_invoke(const Function& function,
  116. buffered_fill_handler<ReadHandler>* this_handler)
  117. {
  118. asio_handler_invoke_helpers::invoke(
  119. function, this_handler->handler_);
  120. }
  121. } // namespace detail
  122. template <typename Stream>
  123. template <typename ReadHandler>
  124. ASIO_INITFN_RESULT_TYPE(ReadHandler,
  125. void (asio::error_code, std::size_t))
  126. buffered_read_stream<Stream>::async_fill(
  127. ASIO_MOVE_ARG(ReadHandler) handler)
  128. {
  129. // If you get an error on the following line it means that your handler does
  130. // not meet the documented type requirements for a ReadHandler.
  131. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  132. detail::async_result_init<
  133. ReadHandler, void (asio::error_code, std::size_t)> init(
  134. ASIO_MOVE_CAST(ReadHandler)(handler));
  135. std::size_t previous_size = storage_.size();
  136. storage_.resize(storage_.capacity());
  137. next_layer_.async_read_some(
  138. buffer(
  139. storage_.data() + previous_size,
  140. storage_.size() - previous_size),
  141. detail::buffered_fill_handler<ASIO_HANDLER_TYPE(
  142. ReadHandler, void (asio::error_code, std::size_t))>(
  143. storage_, previous_size, init.handler));
  144. return init.result.get();
  145. }
  146. template <typename Stream>
  147. template <typename MutableBufferSequence>
  148. std::size_t buffered_read_stream<Stream>::read_some(
  149. const MutableBufferSequence& buffers)
  150. {
  151. if (asio::buffer_size(buffers) == 0)
  152. return 0;
  153. if (storage_.empty())
  154. this->fill();
  155. return this->copy(buffers);
  156. }
  157. template <typename Stream>
  158. template <typename MutableBufferSequence>
  159. std::size_t buffered_read_stream<Stream>::read_some(
  160. const MutableBufferSequence& buffers, asio::error_code& ec)
  161. {
  162. ec = asio::error_code();
  163. if (asio::buffer_size(buffers) == 0)
  164. return 0;
  165. if (storage_.empty() && !this->fill(ec))
  166. return 0;
  167. return this->copy(buffers);
  168. }
  169. namespace detail
  170. {
  171. template <typename MutableBufferSequence, typename ReadHandler>
  172. class buffered_read_some_handler
  173. {
  174. public:
  175. buffered_read_some_handler(detail::buffered_stream_storage& storage,
  176. const MutableBufferSequence& buffers, ReadHandler& handler)
  177. : storage_(storage),
  178. buffers_(buffers),
  179. handler_(handler)
  180. {
  181. }
  182. #if defined(ASIO_HAS_MOVE)
  183. buffered_read_some_handler(const buffered_read_some_handler& other)
  184. : storage_(other.storage_),
  185. buffers_(other.buffers_),
  186. handler_(other.handler_)
  187. {
  188. }
  189. buffered_read_some_handler(buffered_read_some_handler&& other)
  190. : storage_(other.storage_),
  191. buffers_(other.buffers_),
  192. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  193. {
  194. }
  195. #endif // defined(ASIO_HAS_MOVE)
  196. void operator()(const asio::error_code& ec, std::size_t)
  197. {
  198. if (ec || storage_.empty())
  199. {
  200. const std::size_t length = 0;
  201. handler_(ec, length);
  202. }
  203. else
  204. {
  205. const std::size_t bytes_copied = asio::buffer_copy(
  206. buffers_, storage_.data(), storage_.size());
  207. storage_.consume(bytes_copied);
  208. handler_(ec, bytes_copied);
  209. }
  210. }
  211. //private:
  212. detail::buffered_stream_storage& storage_;
  213. MutableBufferSequence buffers_;
  214. ReadHandler handler_;
  215. };
  216. template <typename MutableBufferSequence, typename ReadHandler>
  217. inline void* asio_handler_allocate(std::size_t size,
  218. buffered_read_some_handler<
  219. MutableBufferSequence, ReadHandler>* this_handler)
  220. {
  221. return asio_handler_alloc_helpers::allocate(
  222. size, this_handler->handler_);
  223. }
  224. template <typename MutableBufferSequence, typename ReadHandler>
  225. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  226. buffered_read_some_handler<
  227. MutableBufferSequence, ReadHandler>* this_handler)
  228. {
  229. asio_handler_alloc_helpers::deallocate(
  230. pointer, size, this_handler->handler_);
  231. }
  232. template <typename MutableBufferSequence, typename ReadHandler>
  233. inline bool asio_handler_is_continuation(
  234. buffered_read_some_handler<
  235. MutableBufferSequence, ReadHandler>* this_handler)
  236. {
  237. return asio_handler_cont_helpers::is_continuation(
  238. this_handler->handler_);
  239. }
  240. template <typename Function, typename MutableBufferSequence,
  241. typename ReadHandler>
  242. inline void asio_handler_invoke(Function& function,
  243. buffered_read_some_handler<
  244. MutableBufferSequence, ReadHandler>* this_handler)
  245. {
  246. asio_handler_invoke_helpers::invoke(
  247. function, this_handler->handler_);
  248. }
  249. template <typename Function, typename MutableBufferSequence,
  250. typename ReadHandler>
  251. inline void asio_handler_invoke(const Function& function,
  252. buffered_read_some_handler<
  253. MutableBufferSequence, ReadHandler>* this_handler)
  254. {
  255. asio_handler_invoke_helpers::invoke(
  256. function, this_handler->handler_);
  257. }
  258. } // namespace detail
  259. template <typename Stream>
  260. template <typename MutableBufferSequence, typename ReadHandler>
  261. ASIO_INITFN_RESULT_TYPE(ReadHandler,
  262. void (asio::error_code, std::size_t))
  263. buffered_read_stream<Stream>::async_read_some(
  264. const MutableBufferSequence& buffers,
  265. ASIO_MOVE_ARG(ReadHandler) handler)
  266. {
  267. // If you get an error on the following line it means that your handler does
  268. // not meet the documented type requirements for a ReadHandler.
  269. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  270. detail::async_result_init<
  271. ReadHandler, void (asio::error_code, std::size_t)> init(
  272. ASIO_MOVE_CAST(ReadHandler)(handler));
  273. if (asio::buffer_size(buffers) == 0 || !storage_.empty())
  274. {
  275. next_layer_.async_read_some(asio::mutable_buffers_1(0, 0),
  276. detail::buffered_read_some_handler<
  277. MutableBufferSequence, ASIO_HANDLER_TYPE(
  278. ReadHandler, void (asio::error_code, std::size_t))>(
  279. storage_, buffers, init.handler));
  280. }
  281. else
  282. {
  283. this->async_fill(detail::buffered_read_some_handler<
  284. MutableBufferSequence, ASIO_HANDLER_TYPE(
  285. ReadHandler, void (asio::error_code, std::size_t))>(
  286. storage_, buffers, init.handler));
  287. }
  288. return init.result.get();
  289. }
  290. template <typename Stream>
  291. template <typename MutableBufferSequence>
  292. std::size_t buffered_read_stream<Stream>::peek(
  293. const MutableBufferSequence& buffers)
  294. {
  295. if (storage_.empty())
  296. this->fill();
  297. return this->peek_copy(buffers);
  298. }
  299. template <typename Stream>
  300. template <typename MutableBufferSequence>
  301. std::size_t buffered_read_stream<Stream>::peek(
  302. const MutableBufferSequence& buffers, asio::error_code& ec)
  303. {
  304. ec = asio::error_code();
  305. if (storage_.empty() && !this->fill(ec))
  306. return 0;
  307. return this->peek_copy(buffers);
  308. }
  309. } // namespace asio
  310. #include "asio/detail/pop_options.hpp"
  311. #endif // ASIO_IMPL_BUFFERED_READ_STREAM_HPP