1//
2// buffered_stream.hpp
3// ~~~~~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2024 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
29namespace boost {
30namespace 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 */
44template <typename Stream>
45class buffered_stream
46 : private noncopyable
47{
48public:
49 /// The type of the next layer.
50 typedef remove_reference_t<Stream> 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>
60 explicit buffered_stream(Arg&& a)
61 : inner_stream_impl_(static_cast<Arg&&>(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>
68 explicit buffered_stream(Arg&& a,
69 std::size_t read_buffer_size, std::size_t write_buffer_size)
70 : inner_stream_impl_(static_cast<Arg&&>(a), write_buffer_size),
71 stream_impl_(inner_stream_impl_, read_buffer_size)
72 {
73 }
74
75 /// Get a reference to the 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.
82 lowest_layer_type& lowest_layer()
83 {
84 return stream_impl_.lowest_layer();
85 }
86
87 /// Get a const reference to the lowest layer.
88 const lowest_layer_type& lowest_layer() const
89 {
90 return stream_impl_.lowest_layer();
91 }
92
93 /// Get the executor associated with the object.
94 executor_type get_executor() noexcept
95 {
96 return stream_impl_.lowest_layer().get_executor();
97 }
98
99 /// Close the stream.
100 void close()
101 {
102 stream_impl_.close();
103 }
104
105 /// Close the stream.
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.
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.
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 /**
130 * @par Completion Signature
131 * @code void(boost::system::error_code, std::size_t) @endcode
132 */
133 template <
134 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
135 std::size_t)) WriteHandler = default_completion_token_t<executor_type>>
136 auto async_flush(
137 WriteHandler&& handler = default_completion_token_t<executor_type>())
138 -> decltype(
139 declval<buffered_write_stream<Stream>&>().async_flush(
140 static_cast<WriteHandler&&>(handler)))
141 {
142 return stream_impl_.next_layer().async_flush(
143 static_cast<WriteHandler&&>(handler));
144 }
145
146 /// Write the given data to the stream. Returns the number of bytes written.
147 /// Throws an exception on failure.
148 template <typename ConstBufferSequence>
149 std::size_t write_some(const ConstBufferSequence& buffers)
150 {
151 return stream_impl_.write_some(buffers);
152 }
153
154 /// Write the given data to the stream. Returns the number of bytes written,
155 /// or 0 if an error occurred.
156 template <typename ConstBufferSequence>
157 std::size_t write_some(const ConstBufferSequence& buffers,
158 boost::system::error_code& ec)
159 {
160 return stream_impl_.write_some(buffers, ec);
161 }
162
163 /// Start an asynchronous write. The data being written must be valid for the
164 /// lifetime of the asynchronous operation.
165 /**
166 * @par Completion Signature
167 * @code void(boost::system::error_code, std::size_t) @endcode
168 */
169 template <typename ConstBufferSequence,
170 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
171 std::size_t)) WriteHandler = default_completion_token_t<executor_type>>
172 auto async_write_some(const ConstBufferSequence& buffers,
173 WriteHandler&& handler = default_completion_token_t<executor_type>())
174 -> decltype(
175 declval<Stream&>().async_write_some(buffers,
176 static_cast<WriteHandler&&>(handler)))
177 {
178 return stream_impl_.async_write_some(buffers,
179 static_cast<WriteHandler&&>(handler));
180 }
181
182 /// Fill the buffer with some data. Returns the number of bytes placed in the
183 /// buffer as a result of the operation. Throws an exception on failure.
184 std::size_t fill()
185 {
186 return stream_impl_.fill();
187 }
188
189 /// Fill the buffer with some data. Returns the number of bytes placed in the
190 /// buffer as a result of the operation, or 0 if an error occurred.
191 std::size_t fill(boost::system::error_code& ec)
192 {
193 return stream_impl_.fill(ec);
194 }
195
196 /// Start an asynchronous fill.
197 /**
198 * @par Completion Signature
199 * @code void(boost::system::error_code, std::size_t) @endcode
200 */
201 template <
202 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
203 std::size_t)) ReadHandler = default_completion_token_t<executor_type>>
204 auto async_fill(
205 ReadHandler&& handler = default_completion_token_t<executor_type>())
206 -> decltype(
207 declval<buffered_read_stream<
208 buffered_write_stream<Stream>>&>().async_fill(
209 static_cast<ReadHandler&&>(handler)))
210 {
211 return stream_impl_.async_fill(static_cast<ReadHandler&&>(handler));
212 }
213
214 /// Read some data from the stream. Returns the number of bytes read. Throws
215 /// an exception on failure.
216 template <typename MutableBufferSequence>
217 std::size_t read_some(const MutableBufferSequence& buffers)
218 {
219 return stream_impl_.read_some(buffers);
220 }
221
222 /// Read some data from the stream. Returns the number of bytes read or 0 if
223 /// an error occurred.
224 template <typename MutableBufferSequence>
225 std::size_t read_some(const MutableBufferSequence& buffers,
226 boost::system::error_code& ec)
227 {
228 return stream_impl_.read_some(buffers, ec);
229 }
230
231 /// Start an asynchronous read. The buffer into which the data will be read
232 /// must be valid for the lifetime of the asynchronous operation.
233 /**
234 * @par Completion Signature
235 * @code void(boost::system::error_code, std::size_t) @endcode
236 */
237 template <typename MutableBufferSequence,
238 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
239 std::size_t)) ReadHandler = default_completion_token_t<executor_type>>
240 auto async_read_some(const MutableBufferSequence& buffers,
241 ReadHandler&& handler = default_completion_token_t<executor_type>())
242 -> decltype(
243 declval<Stream&>().async_read_some(buffers,
244 static_cast<ReadHandler&&>(handler)))
245 {
246 return stream_impl_.async_read_some(buffers,
247 static_cast<ReadHandler&&>(handler));
248 }
249
250 /// Peek at the incoming data on the stream. Returns the number of bytes read.
251 /// Throws an exception on failure.
252 template <typename MutableBufferSequence>
253 std::size_t peek(const MutableBufferSequence& buffers)
254 {
255 return stream_impl_.peek(buffers);
256 }
257
258 /// Peek at the incoming data on the stream. Returns the number of bytes read,
259 /// or 0 if an error occurred.
260 template <typename MutableBufferSequence>
261 std::size_t peek(const MutableBufferSequence& buffers,
262 boost::system::error_code& ec)
263 {
264 return stream_impl_.peek(buffers, ec);
265 }
266
267 /// Determine the amount of data that may be read without blocking.
268 std::size_t in_avail()
269 {
270 return stream_impl_.in_avail();
271 }
272
273 /// Determine the amount of data that may be read without blocking.
274 std::size_t in_avail(boost::system::error_code& ec)
275 {
276 return stream_impl_.in_avail(ec);
277 }
278
279private:
280 // The buffered write stream.
281 typedef buffered_write_stream<Stream> write_stream_type;
282 write_stream_type inner_stream_impl_;
283
284 // The buffered read stream.
285 typedef buffered_read_stream<write_stream_type&> read_stream_type;
286 read_stream_type stream_impl_;
287};
288
289} // namespace asio
290} // namespace boost
291
292#include <boost/asio/detail/pop_options.hpp>
293
294#endif // BOOST_ASIO_BUFFERED_STREAM_HPP
295

source code of boost/libs/asio/include/boost/asio/buffered_stream.hpp