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

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