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