1 // 2 // buffered_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 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 #include <boost/asio/io_service.hpp> 27 28 #include <boost/asio/detail/push_options.hpp> 29 30 namespace boost { 31 namespace asio { 32 33 /// Adds buffering to the read- and write-related operations of a stream. 34 /** 35 * The buffered_stream class template can be used to add buffering to the 36 * synchronous and asynchronous read and write operations of a stream. 37 * 38 * @par Thread Safety 39 * @e Distinct @e objects: Safe.@n 40 * @e Shared @e objects: Unsafe. 41 * 42 * @par Concepts: 43 * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. 44 */ 45 template <typename Stream> 46 class buffered_stream 47 : private noncopyable 48 { 49 public: 50 /// The type of the next layer. 51 typedef typename remove_reference<Stream>::type next_layer_type; 52 53 /// The type of the lowest layer. 54 typedef typename next_layer_type::lowest_layer_type lowest_layer_type; 55 56 /// Construct, passing the specified argument to initialise the next layer. 57 template <typename Arg> buffered_stream(Arg & a)58 explicit buffered_stream(Arg& a) 59 : inner_stream_impl_(a), 60 stream_impl_(inner_stream_impl_) 61 { 62 } 63 64 /// Construct, passing the specified argument to initialise the next layer. 65 template <typename Arg> buffered_stream(Arg & a,std::size_t read_buffer_size,std::size_t write_buffer_size)66 explicit buffered_stream(Arg& a, std::size_t read_buffer_size, 67 std::size_t write_buffer_size) 68 : inner_stream_impl_(a, write_buffer_size), 69 stream_impl_(inner_stream_impl_, read_buffer_size) 70 { 71 } 72 73 /// Get a reference to the next layer. next_layer()74 next_layer_type& next_layer() 75 { 76 return stream_impl_.next_layer().next_layer(); 77 } 78 79 /// Get a reference to the lowest layer. lowest_layer()80 lowest_layer_type& lowest_layer() 81 { 82 return stream_impl_.lowest_layer(); 83 } 84 85 /// Get a const reference to the lowest layer. lowest_layer() const86 const lowest_layer_type& lowest_layer() const 87 { 88 return stream_impl_.lowest_layer(); 89 } 90 91 /// Get the io_service associated with the object. get_io_service()92 boost::asio::io_service& get_io_service() 93 { 94 return stream_impl_.get_io_service(); 95 } 96 97 /// Close the stream. close()98 void close() 99 { 100 stream_impl_.close(); 101 } 102 103 /// Close the stream. close(boost::system::error_code & ec)104 boost::system::error_code close(boost::system::error_code& ec) 105 { 106 return stream_impl_.close(ec); 107 } 108 109 /// Flush all data from the buffer to the next layer. Returns the number of 110 /// bytes written to the next layer on the last write operation. Throws an 111 /// exception on failure. flush()112 std::size_t flush() 113 { 114 return stream_impl_.next_layer().flush(); 115 } 116 117 /// Flush all data from the buffer to the next layer. Returns the number of 118 /// bytes written to the next layer on the last write operation, or 0 if an 119 /// error occurred. flush(boost::system::error_code & ec)120 std::size_t flush(boost::system::error_code& ec) 121 { 122 return stream_impl_.next_layer().flush(ec); 123 } 124 125 /// Start an asynchronous flush. 126 template <typename WriteHandler> BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,void (boost::system::error_code,std::size_t))127 BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, 128 void (boost::system::error_code, std::size_t)) 129 async_flush(BOOST_ASIO_MOVE_ARG(WriteHandler) handler) 130 { 131 return stream_impl_.next_layer().async_flush( 132 BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); 133 } 134 135 /// Write the given data to the stream. Returns the number of bytes written. 136 /// Throws an exception on failure. 137 template <typename ConstBufferSequence> write_some(const ConstBufferSequence & buffers)138 std::size_t write_some(const ConstBufferSequence& buffers) 139 { 140 return stream_impl_.write_some(buffers); 141 } 142 143 /// Write the given data to the stream. Returns the number of bytes written, 144 /// or 0 if an error occurred. 145 template <typename ConstBufferSequence> write_some(const ConstBufferSequence & buffers,boost::system::error_code & ec)146 std::size_t write_some(const ConstBufferSequence& buffers, 147 boost::system::error_code& ec) 148 { 149 return stream_impl_.write_some(buffers, ec); 150 } 151 152 /// Start an asynchronous write. The data being written must be valid for the 153 /// lifetime of the asynchronous operation. 154 template <typename ConstBufferSequence, typename WriteHandler> BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,void (boost::system::error_code,std::size_t))155 BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, 156 void (boost::system::error_code, std::size_t)) 157 async_write_some(const ConstBufferSequence& buffers, 158 BOOST_ASIO_MOVE_ARG(WriteHandler) handler) 159 { 160 return stream_impl_.async_write_some(buffers, 161 BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); 162 } 163 164 /// Fill the buffer with some data. Returns the number of bytes placed in the 165 /// buffer as a result of the operation. Throws an exception on failure. fill()166 std::size_t fill() 167 { 168 return stream_impl_.fill(); 169 } 170 171 /// Fill the buffer with some data. Returns the number of bytes placed in the 172 /// buffer as a result of the operation, or 0 if an error occurred. fill(boost::system::error_code & ec)173 std::size_t fill(boost::system::error_code& ec) 174 { 175 return stream_impl_.fill(ec); 176 } 177 178 /// Start an asynchronous fill. 179 template <typename ReadHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))180 BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, 181 void (boost::system::error_code, std::size_t)) 182 async_fill(BOOST_ASIO_MOVE_ARG(ReadHandler) handler) 183 { 184 return stream_impl_.async_fill(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); 185 } 186 187 /// Read some data from the stream. Returns the number of bytes read. Throws 188 /// an exception on failure. 189 template <typename MutableBufferSequence> read_some(const MutableBufferSequence & buffers)190 std::size_t read_some(const MutableBufferSequence& buffers) 191 { 192 return stream_impl_.read_some(buffers); 193 } 194 195 /// Read some data from the stream. Returns the number of bytes read or 0 if 196 /// an error occurred. 197 template <typename MutableBufferSequence> read_some(const MutableBufferSequence & buffers,boost::system::error_code & ec)198 std::size_t read_some(const MutableBufferSequence& buffers, 199 boost::system::error_code& ec) 200 { 201 return stream_impl_.read_some(buffers, ec); 202 } 203 204 /// Start an asynchronous read. The buffer into which the data will be read 205 /// must be valid for the lifetime of the asynchronous operation. 206 template <typename MutableBufferSequence, typename ReadHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))207 BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, 208 void (boost::system::error_code, std::size_t)) 209 async_read_some(const MutableBufferSequence& buffers, 210 BOOST_ASIO_MOVE_ARG(ReadHandler) handler) 211 { 212 return stream_impl_.async_read_some(buffers, 213 BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); 214 } 215 216 /// Peek at the incoming data on the stream. Returns the number of bytes read. 217 /// Throws an exception on failure. 218 template <typename MutableBufferSequence> peek(const MutableBufferSequence & buffers)219 std::size_t peek(const MutableBufferSequence& buffers) 220 { 221 return stream_impl_.peek(buffers); 222 } 223 224 /// Peek at the incoming data on the stream. Returns the number of bytes read, 225 /// or 0 if an error occurred. 226 template <typename MutableBufferSequence> peek(const MutableBufferSequence & buffers,boost::system::error_code & ec)227 std::size_t peek(const MutableBufferSequence& buffers, 228 boost::system::error_code& ec) 229 { 230 return stream_impl_.peek(buffers, ec); 231 } 232 233 /// Determine the amount of data that may be read without blocking. in_avail()234 std::size_t in_avail() 235 { 236 return stream_impl_.in_avail(); 237 } 238 239 /// Determine the amount of data that may be read without blocking. in_avail(boost::system::error_code & ec)240 std::size_t in_avail(boost::system::error_code& ec) 241 { 242 return stream_impl_.in_avail(ec); 243 } 244 245 private: 246 // The buffered write stream. 247 typedef buffered_write_stream<Stream> write_stream_type; 248 write_stream_type inner_stream_impl_; 249 250 // The buffered read stream. 251 typedef buffered_read_stream<write_stream_type&> read_stream_type; 252 read_stream_type stream_impl_; 253 }; 254 255 } // namespace asio 256 } // namespace boost 257 258 #include <boost/asio/detail/pop_options.hpp> 259 260 #endif // BOOST_ASIO_BUFFERED_STREAM_HPP 261