buffered_read_stream.hpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. //
  2. // buffered_read_stream.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2023 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_BUFFERED_READ_STREAM_HPP
  11. #define ASIO_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/config.hpp"
  16. #include <cstddef>
  17. #include "asio/async_result.hpp"
  18. #include "asio/buffered_read_stream_fwd.hpp"
  19. #include "asio/buffer.hpp"
  20. #include "asio/detail/bind_handler.hpp"
  21. #include "asio/detail/buffer_resize_guard.hpp"
  22. #include "asio/detail/buffered_stream_storage.hpp"
  23. #include "asio/detail/noncopyable.hpp"
  24. #include "asio/detail/type_traits.hpp"
  25. #include "asio/error.hpp"
  26. #include "asio/detail/push_options.hpp"
  27. namespace asio {
  28. namespace detail {
  29. template <typename> class initiate_async_buffered_fill;
  30. template <typename> class initiate_async_buffered_read_some;
  31. } // namespace detail
  32. /// Adds buffering to the read-related operations of a stream.
  33. /**
  34. * The buffered_read_stream class template can be used to add buffering to the
  35. * synchronous and asynchronous read operations of a stream.
  36. *
  37. * @par Thread Safety
  38. * @e Distinct @e objects: Safe.@n
  39. * @e Shared @e objects: Unsafe.
  40. *
  41. * @par Concepts:
  42. * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
  43. */
  44. template <typename Stream>
  45. class buffered_read_stream
  46. : private noncopyable
  47. {
  48. public:
  49. /// The type of the next layer.
  50. typedef remove_reference_t<Stream> next_layer_type;
  51. /// The type of the lowest layer.
  52. typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
  53. /// The type of the executor associated with the object.
  54. typedef typename lowest_layer_type::executor_type executor_type;
  55. #if defined(GENERATING_DOCUMENTATION)
  56. /// The default buffer size.
  57. static const std::size_t default_buffer_size = implementation_defined;
  58. #else
  59. ASIO_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024);
  60. #endif
  61. /// Construct, passing the specified argument to initialise the next layer.
  62. template <typename Arg>
  63. explicit buffered_read_stream(Arg&& a)
  64. : next_layer_(static_cast<Arg&&>(a)),
  65. storage_(default_buffer_size)
  66. {
  67. }
  68. /// Construct, passing the specified argument to initialise the next layer.
  69. template <typename Arg>
  70. buffered_read_stream(Arg&& a,
  71. std::size_t buffer_size)
  72. : next_layer_(static_cast<Arg&&>(a)),
  73. storage_(buffer_size)
  74. {
  75. }
  76. /// Get a reference to the next layer.
  77. next_layer_type& next_layer()
  78. {
  79. return next_layer_;
  80. }
  81. /// Get a reference to the lowest layer.
  82. lowest_layer_type& lowest_layer()
  83. {
  84. return next_layer_.lowest_layer();
  85. }
  86. /// Get a const reference to the lowest layer.
  87. const lowest_layer_type& lowest_layer() const
  88. {
  89. return next_layer_.lowest_layer();
  90. }
  91. /// Get the executor associated with the object.
  92. executor_type get_executor() noexcept
  93. {
  94. return next_layer_.lowest_layer().get_executor();
  95. }
  96. /// Close the stream.
  97. void close()
  98. {
  99. next_layer_.close();
  100. }
  101. /// Close the stream.
  102. ASIO_SYNC_OP_VOID close(asio::error_code& ec)
  103. {
  104. next_layer_.close(ec);
  105. ASIO_SYNC_OP_VOID_RETURN(ec);
  106. }
  107. /// Write the given data to the stream. Returns the number of bytes written.
  108. /// Throws an exception on failure.
  109. template <typename ConstBufferSequence>
  110. std::size_t write_some(const ConstBufferSequence& buffers)
  111. {
  112. return next_layer_.write_some(buffers);
  113. }
  114. /// Write the given data to the stream. Returns the number of bytes written,
  115. /// or 0 if an error occurred.
  116. template <typename ConstBufferSequence>
  117. std::size_t write_some(const ConstBufferSequence& buffers,
  118. asio::error_code& ec)
  119. {
  120. return next_layer_.write_some(buffers, ec);
  121. }
  122. /// Start an asynchronous write. The data being written must be valid for the
  123. /// lifetime of the asynchronous operation.
  124. /**
  125. * @par Completion Signature
  126. * @code void(asio::error_code, std::size_t) @endcode
  127. */
  128. template <typename ConstBufferSequence,
  129. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  130. std::size_t)) WriteHandler = default_completion_token_t<executor_type>>
  131. auto async_write_some(const ConstBufferSequence& buffers,
  132. WriteHandler&& handler = default_completion_token_t<executor_type>())
  133. -> decltype(
  134. declval<conditional_t<true, Stream&, WriteHandler>>().async_write_some(
  135. buffers, static_cast<WriteHandler&&>(handler)))
  136. {
  137. return next_layer_.async_write_some(buffers,
  138. static_cast<WriteHandler&&>(handler));
  139. }
  140. /// Fill the buffer with some data. Returns the number of bytes placed in the
  141. /// buffer as a result of the operation. Throws an exception on failure.
  142. std::size_t fill();
  143. /// Fill the buffer with some data. Returns the number of bytes placed in the
  144. /// buffer as a result of the operation, or 0 if an error occurred.
  145. std::size_t fill(asio::error_code& ec);
  146. /// Start an asynchronous fill.
  147. /**
  148. * @par Completion Signature
  149. * @code void(asio::error_code, std::size_t) @endcode
  150. */
  151. template <
  152. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  153. std::size_t)) ReadHandler = default_completion_token_t<executor_type>>
  154. auto async_fill(
  155. ReadHandler&& handler = default_completion_token_t<executor_type>())
  156. -> decltype(
  157. async_initiate<ReadHandler,
  158. void (asio::error_code, std::size_t)>(
  159. declval<detail::initiate_async_buffered_fill<Stream>>(),
  160. handler, declval<detail::buffered_stream_storage*>()));
  161. /// Read some data from the stream. Returns the number of bytes read. Throws
  162. /// an exception on failure.
  163. template <typename MutableBufferSequence>
  164. std::size_t read_some(const MutableBufferSequence& buffers);
  165. /// Read some data from the stream. Returns the number of bytes read or 0 if
  166. /// an error occurred.
  167. template <typename MutableBufferSequence>
  168. std::size_t read_some(const MutableBufferSequence& buffers,
  169. asio::error_code& ec);
  170. /// Start an asynchronous read. The buffer into which the data will be read
  171. /// must be valid for the lifetime of the asynchronous operation.
  172. /**
  173. * @par Completion Signature
  174. * @code void(asio::error_code, std::size_t) @endcode
  175. */
  176. template <typename MutableBufferSequence,
  177. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  178. std::size_t)) ReadHandler = default_completion_token_t<executor_type>>
  179. auto async_read_some(const MutableBufferSequence& buffers,
  180. ReadHandler&& handler = default_completion_token_t<executor_type>())
  181. -> decltype(
  182. async_initiate<ReadHandler,
  183. void (asio::error_code, std::size_t)>(
  184. declval<detail::initiate_async_buffered_read_some<Stream>>(),
  185. handler, declval<detail::buffered_stream_storage*>(), buffers));
  186. /// Peek at the incoming data on the stream. Returns the number of bytes read.
  187. /// Throws an exception on failure.
  188. template <typename MutableBufferSequence>
  189. std::size_t peek(const MutableBufferSequence& buffers);
  190. /// Peek at the incoming data on the stream. Returns the number of bytes read,
  191. /// or 0 if an error occurred.
  192. template <typename MutableBufferSequence>
  193. std::size_t peek(const MutableBufferSequence& buffers,
  194. asio::error_code& ec);
  195. /// Determine the amount of data that may be read without blocking.
  196. std::size_t in_avail()
  197. {
  198. return storage_.size();
  199. }
  200. /// Determine the amount of data that may be read without blocking.
  201. std::size_t in_avail(asio::error_code& ec)
  202. {
  203. ec = asio::error_code();
  204. return storage_.size();
  205. }
  206. private:
  207. /// Copy data out of the internal buffer to the specified target buffer.
  208. /// Returns the number of bytes copied.
  209. template <typename MutableBufferSequence>
  210. std::size_t copy(const MutableBufferSequence& buffers)
  211. {
  212. std::size_t bytes_copied = asio::buffer_copy(
  213. buffers, storage_.data(), storage_.size());
  214. storage_.consume(bytes_copied);
  215. return bytes_copied;
  216. }
  217. /// Copy data from the internal buffer to the specified target buffer, without
  218. /// removing the data from the internal buffer. Returns the number of bytes
  219. /// copied.
  220. template <typename MutableBufferSequence>
  221. std::size_t peek_copy(const MutableBufferSequence& buffers)
  222. {
  223. return asio::buffer_copy(buffers, storage_.data(), storage_.size());
  224. }
  225. /// The next layer.
  226. Stream next_layer_;
  227. // The data in the buffer.
  228. detail::buffered_stream_storage storage_;
  229. };
  230. } // namespace asio
  231. #include "asio/detail/pop_options.hpp"
  232. #include "asio/impl/buffered_read_stream.hpp"
  233. #endif // ASIO_BUFFERED_READ_STREAM_HPP