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