1 // 2 // buffered_stream.hpp 3 // ~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2021 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 11 #ifndef BOOST_ASIO_BUFFERED_STREAM_HPP 12 #define BOOST_ASIO_BUFFERED_STREAM_HPP 13 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18 #include <boost/asio/detail/config.hpp> 19 #include <cstddef> 20 #include <boost/asio/async_result.hpp> 21 #include <boost/asio/buffered_read_stream.hpp> 22 #include <boost/asio/buffered_write_stream.hpp> 23 #include <boost/asio/buffered_stream_fwd.hpp> 24 #include <boost/asio/detail/noncopyable.hpp> 25 #include <boost/asio/error.hpp> 26 27 #include <boost/asio/detail/push_options.hpp> 28 29 namespace boost { 30 namespace asio { 31 32 /// Adds buffering to the read- and write-related operations of a stream. 33 /** 34 * The buffered_stream class template can be used to add buffering to the 35 * synchronous and asynchronous read and write 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_stream 46 : private noncopyable 47 { 48 public: 49 /// The type of the next layer. 50 typedef typename remove_reference<Stream>::type next_layer_type; 51 52 /// The type of the lowest layer. 53 typedef typename next_layer_type::lowest_layer_type lowest_layer_type; 54 55 /// The type of the executor associated with the object. 56 typedef typename lowest_layer_type::executor_type executor_type; 57 58 /// Construct, passing the specified argument to initialise the next layer. 59 template <typename Arg> buffered_stream(Arg & a)60 explicit buffered_stream(Arg& a) 61 : inner_stream_impl_(a), 62 stream_impl_(inner_stream_impl_) 63 { 64 } 65 66 /// Construct, passing the specified argument to initialise the next layer. 67 template <typename Arg> buffered_stream(Arg & a,std::size_t read_buffer_size,std::size_t write_buffer_size)68 explicit buffered_stream(Arg& a, std::size_t read_buffer_size, 69 std::size_t write_buffer_size) 70 : inner_stream_impl_(a, write_buffer_size), 71 stream_impl_(inner_stream_impl_, read_buffer_size) 72 { 73 } 74 75 /// Get a reference to the next layer. next_layer()76 next_layer_type& next_layer() 77 { 78 return stream_impl_.next_layer().next_layer(); 79 } 80 81 /// Get a reference to the lowest layer. lowest_layer()82 lowest_layer_type& lowest_layer() 83 { 84 return stream_impl_.lowest_layer(); 85 } 86 87 /// Get a const reference to the lowest layer. lowest_layer() const88 const lowest_layer_type& lowest_layer() const 89 { 90 return stream_impl_.lowest_layer(); 91 } 92 93 /// Get the executor associated with the object. get_executor()94 executor_type get_executor() BOOST_ASIO_NOEXCEPT 95 { 96 return stream_impl_.lowest_layer().get_executor(); 97 } 98 99 /// Close the stream. close()100 void close() 101 { 102 stream_impl_.close(); 103 } 104 105 /// Close the stream. close(boost::system::error_code & ec)106 BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) 107 { 108 stream_impl_.close(ec); 109 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 110 } 111 112 /// Flush all data from the buffer to the next layer. Returns the number of 113 /// bytes written to the next layer on the last write operation. Throws an 114 /// exception on failure. flush()115 std::size_t flush() 116 { 117 return stream_impl_.next_layer().flush(); 118 } 119 120 /// Flush all data from the buffer to the next layer. Returns the number of 121 /// bytes written to the next layer on the last write operation, or 0 if an 122 /// error occurred. flush(boost::system::error_code & ec)123 std::size_t flush(boost::system::error_code& ec) 124 { 125 return stream_impl_.next_layer().flush(ec); 126 } 127 128 /// Start an asynchronous flush. 129 template < 130 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 131 std::size_t)) WriteHandler 132 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,void (boost::system::error_code,std::size_t))133 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, 134 void (boost::system::error_code, std::size_t)) 135 async_flush( 136 BOOST_ASIO_MOVE_ARG(WriteHandler) handler 137 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) 138 { 139 return stream_impl_.next_layer().async_flush( 140 BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); 141 } 142 143 /// Write the given data to the stream. Returns the number of bytes written. 144 /// Throws an exception on failure. 145 template <typename ConstBufferSequence> write_some(const ConstBufferSequence & buffers)146 std::size_t write_some(const ConstBufferSequence& buffers) 147 { 148 return stream_impl_.write_some(buffers); 149 } 150 151 /// Write the given data to the stream. Returns the number of bytes written, 152 /// or 0 if an error occurred. 153 template <typename ConstBufferSequence> write_some(const ConstBufferSequence & buffers,boost::system::error_code & ec)154 std::size_t write_some(const ConstBufferSequence& buffers, 155 boost::system::error_code& ec) 156 { 157 return stream_impl_.write_some(buffers, ec); 158 } 159 160 /// Start an asynchronous write. The data being written must be valid for the 161 /// lifetime of the asynchronous operation. 162 template <typename ConstBufferSequence, 163 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 164 std::size_t)) WriteHandler 165 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,void (boost::system::error_code,std::size_t))166 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, 167 void (boost::system::error_code, std::size_t)) 168 async_write_some(const ConstBufferSequence& buffers, 169 BOOST_ASIO_MOVE_ARG(WriteHandler) handler 170 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) 171 { 172 return stream_impl_.async_write_some(buffers, 173 BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); 174 } 175 176 /// Fill the buffer with some data. Returns the number of bytes placed in the 177 /// buffer as a result of the operation. Throws an exception on failure. fill()178 std::size_t fill() 179 { 180 return stream_impl_.fill(); 181 } 182 183 /// Fill the buffer with some data. Returns the number of bytes placed in the 184 /// buffer as a result of the operation, or 0 if an error occurred. fill(boost::system::error_code & ec)185 std::size_t fill(boost::system::error_code& ec) 186 { 187 return stream_impl_.fill(ec); 188 } 189 190 /// Start an asynchronous fill. 191 template < 192 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 193 std::size_t)) ReadHandler 194 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))195 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, 196 void (boost::system::error_code, std::size_t)) 197 async_fill( 198 BOOST_ASIO_MOVE_ARG(ReadHandler) handler 199 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) 200 { 201 return stream_impl_.async_fill(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); 202 } 203 204 /// Read some data from the stream. Returns the number of bytes read. Throws 205 /// an exception on failure. 206 template <typename MutableBufferSequence> read_some(const MutableBufferSequence & buffers)207 std::size_t read_some(const MutableBufferSequence& buffers) 208 { 209 return stream_impl_.read_some(buffers); 210 } 211 212 /// Read some data from the stream. Returns the number of bytes read or 0 if 213 /// an error occurred. 214 template <typename MutableBufferSequence> read_some(const MutableBufferSequence & buffers,boost::system::error_code & ec)215 std::size_t read_some(const MutableBufferSequence& buffers, 216 boost::system::error_code& ec) 217 { 218 return stream_impl_.read_some(buffers, ec); 219 } 220 221 /// Start an asynchronous read. The buffer into which the data will be read 222 /// must be valid for the lifetime of the asynchronous operation. 223 template <typename MutableBufferSequence, 224 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 225 std::size_t)) ReadHandler 226 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))227 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, 228 void (boost::system::error_code, std::size_t)) 229 async_read_some(const MutableBufferSequence& buffers, 230 BOOST_ASIO_MOVE_ARG(ReadHandler) handler 231 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) 232 { 233 return stream_impl_.async_read_some(buffers, 234 BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); 235 } 236 237 /// Peek at the incoming data on the stream. Returns the number of bytes read. 238 /// Throws an exception on failure. 239 template <typename MutableBufferSequence> peek(const MutableBufferSequence & buffers)240 std::size_t peek(const MutableBufferSequence& buffers) 241 { 242 return stream_impl_.peek(buffers); 243 } 244 245 /// Peek at the incoming data on the stream. Returns the number of bytes read, 246 /// or 0 if an error occurred. 247 template <typename MutableBufferSequence> peek(const MutableBufferSequence & buffers,boost::system::error_code & ec)248 std::size_t peek(const MutableBufferSequence& buffers, 249 boost::system::error_code& ec) 250 { 251 return stream_impl_.peek(buffers, ec); 252 } 253 254 /// Determine the amount of data that may be read without blocking. in_avail()255 std::size_t in_avail() 256 { 257 return stream_impl_.in_avail(); 258 } 259 260 /// Determine the amount of data that may be read without blocking. in_avail(boost::system::error_code & ec)261 std::size_t in_avail(boost::system::error_code& ec) 262 { 263 return stream_impl_.in_avail(ec); 264 } 265 266 private: 267 // The buffered write stream. 268 typedef buffered_write_stream<Stream> write_stream_type; 269 write_stream_type inner_stream_impl_; 270 271 // The buffered read stream. 272 typedef buffered_read_stream<write_stream_type&> read_stream_type; 273 read_stream_type stream_impl_; 274 }; 275 276 } // namespace asio 277 } // namespace boost 278 279 #include <boost/asio/detail/pop_options.hpp> 280 281 #endif // BOOST_ASIO_BUFFERED_STREAM_HPP 282