5 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_READ_IPP
12 #define BOOST_ASIO_READ_IPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/push_options.hpp>
20 #include <boost/asio/detail/push_options.hpp>
22 #include <boost/asio/detail/pop_options.hpp>
24 #include <boost/asio/buffer.hpp>
25 #include <boost/asio/completion_condition.hpp>
26 #include <boost/asio/error.hpp>
27 #include <boost/asio/detail/bind_handler.hpp>
28 #include <boost/asio/detail/consuming_buffers.hpp>
29 #include <boost/asio/detail/handler_alloc_helpers.hpp>
30 #include <boost/asio/detail/handler_invoke_helpers.hpp>
31 #include <boost/asio/detail/throw_error.hpp>
36 template <typename SyncReadStream, typename MutableBufferSequence,
37 typename CompletionCondition>
38 std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
39 CompletionCondition completion_condition, boost::system::error_code& ec)
41 ec = boost::system::error_code();
42 boost::asio::detail::consuming_buffers<
43 mutable_buffer, MutableBufferSequence> tmp(buffers);
44 std::size_t total_transferred = 0;
45 tmp.set_max_size(detail::adapt_completion_condition_result(
46 completion_condition(ec, total_transferred)));
47 while (tmp.begin() != tmp.end())
49 std::size_t bytes_transferred = s.read_some(tmp, ec);
50 tmp.consume(bytes_transferred);
51 total_transferred += bytes_transferred;
52 tmp.set_max_size(detail::adapt_completion_condition_result(
53 completion_condition(ec, total_transferred)));
55 return total_transferred;
58 template <typename SyncReadStream, typename MutableBufferSequence>
59 inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers)
61 boost::system::error_code ec;
62 std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
63 boost::asio::detail::throw_error(ec);
64 return bytes_transferred;
67 template <typename SyncReadStream, typename MutableBufferSequence,
68 typename CompletionCondition>
69 inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
70 CompletionCondition completion_condition)
72 boost::system::error_code ec;
73 std::size_t bytes_transferred = read(s, buffers, completion_condition, ec);
74 boost::asio::detail::throw_error(ec);
75 return bytes_transferred;
78 template <typename SyncReadStream, typename Allocator,
79 typename CompletionCondition>
80 std::size_t read(SyncReadStream& s,
81 boost::asio::basic_streambuf<Allocator>& b,
82 CompletionCondition completion_condition, boost::system::error_code& ec)
84 ec = boost::system::error_code();
85 std::size_t total_transferred = 0;
86 std::size_t max_size = detail::adapt_completion_condition_result(
87 completion_condition(ec, total_transferred));
88 std::size_t bytes_available = std::min<std::size_t>(512,
89 std::min<std::size_t>(max_size, b.max_size() - b.size()));
90 while (bytes_available > 0)
92 std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
93 b.commit(bytes_transferred);
94 total_transferred += bytes_transferred;
95 max_size = detail::adapt_completion_condition_result(
96 completion_condition(ec, total_transferred));
97 bytes_available = std::min<std::size_t>(512,
98 std::min<std::size_t>(max_size, b.max_size() - b.size()));
100 return total_transferred;
103 template <typename SyncReadStream, typename Allocator>
104 inline std::size_t read(SyncReadStream& s,
105 boost::asio::basic_streambuf<Allocator>& b)
107 boost::system::error_code ec;
108 std::size_t bytes_transferred = read(s, b, transfer_all(), ec);
109 boost::asio::detail::throw_error(ec);
110 return bytes_transferred;
113 template <typename SyncReadStream, typename Allocator,
114 typename CompletionCondition>
115 inline std::size_t read(SyncReadStream& s,
116 boost::asio::basic_streambuf<Allocator>& b,
117 CompletionCondition completion_condition)
119 boost::system::error_code ec;
120 std::size_t bytes_transferred = read(s, b, completion_condition, ec);
121 boost::asio::detail::throw_error(ec);
122 return bytes_transferred;
127 template <typename AsyncReadStream, typename MutableBufferSequence,
128 typename CompletionCondition, typename ReadHandler>
132 typedef boost::asio::detail::consuming_buffers<
133 mutable_buffer, MutableBufferSequence> buffers_type;
135 read_handler(AsyncReadStream& stream, const buffers_type& buffers,
136 CompletionCondition completion_condition, ReadHandler handler)
139 total_transferred_(0),
140 completion_condition_(completion_condition),
145 void operator()(const boost::system::error_code& ec,
146 std::size_t bytes_transferred)
148 total_transferred_ += bytes_transferred;
149 buffers_.consume(bytes_transferred);
150 buffers_.set_max_size(detail::adapt_completion_condition_result(
151 completion_condition_(ec, total_transferred_)));
152 if (buffers_.begin() == buffers_.end())
154 handler_(ec, total_transferred_);
158 stream_.async_read_some(buffers_, *this);
163 AsyncReadStream& stream_;
164 buffers_type buffers_;
165 std::size_t total_transferred_;
166 CompletionCondition completion_condition_;
167 ReadHandler handler_;
170 template <typename AsyncReadStream, typename MutableBufferSequence,
171 typename CompletionCondition, typename ReadHandler>
172 inline void* asio_handler_allocate(std::size_t size,
173 read_handler<AsyncReadStream, MutableBufferSequence,
174 CompletionCondition, ReadHandler>* this_handler)
176 return boost_asio_handler_alloc_helpers::allocate(
177 size, &this_handler->handler_);
180 template <typename AsyncReadStream, typename MutableBufferSequence,
181 typename CompletionCondition, typename ReadHandler>
182 inline void asio_handler_deallocate(void* pointer, std::size_t size,
183 read_handler<AsyncReadStream, MutableBufferSequence,
184 CompletionCondition, ReadHandler>* this_handler)
186 boost_asio_handler_alloc_helpers::deallocate(
187 pointer, size, &this_handler->handler_);
190 template <typename Function, typename AsyncReadStream,
191 typename MutableBufferSequence, typename CompletionCondition,
192 typename ReadHandler>
193 inline void asio_handler_invoke(const Function& function,
194 read_handler<AsyncReadStream, MutableBufferSequence,
195 CompletionCondition, ReadHandler>* this_handler)
197 boost_asio_handler_invoke_helpers::invoke(
198 function, &this_handler->handler_);
200 } // namespace detail
202 template <typename AsyncReadStream, typename MutableBufferSequence,
203 typename CompletionCondition, typename ReadHandler>
204 inline void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
205 CompletionCondition completion_condition, ReadHandler handler)
207 boost::asio::detail::consuming_buffers<
208 mutable_buffer, MutableBufferSequence> tmp(buffers);
210 boost::system::error_code ec;
211 std::size_t total_transferred = 0;
212 tmp.set_max_size(detail::adapt_completion_condition_result(
213 completion_condition(ec, total_transferred)));
214 if (tmp.begin() == tmp.end())
216 s.get_io_service().post(detail::bind_handler(
217 handler, ec, total_transferred));
221 s.async_read_some(tmp,
222 detail::read_handler<AsyncReadStream, MutableBufferSequence,
223 CompletionCondition, ReadHandler>(
224 s, tmp, completion_condition, handler));
227 template <typename AsyncReadStream, typename MutableBufferSequence,
228 typename ReadHandler>
229 inline void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
232 async_read(s, buffers, transfer_all(), handler);
237 template <typename AsyncReadStream, typename Allocator,
238 typename CompletionCondition, typename ReadHandler>
239 class read_streambuf_handler
242 read_streambuf_handler(AsyncReadStream& stream,
243 basic_streambuf<Allocator>& streambuf,
244 CompletionCondition completion_condition, ReadHandler handler)
246 streambuf_(streambuf),
247 total_transferred_(0),
248 completion_condition_(completion_condition),
253 void operator()(const boost::system::error_code& ec,
254 std::size_t bytes_transferred)
256 total_transferred_ += bytes_transferred;
257 streambuf_.commit(bytes_transferred);
258 std::size_t max_size = detail::adapt_completion_condition_result(
259 completion_condition_(ec, total_transferred_));
260 std::size_t bytes_available = std::min<std::size_t>(512,
261 std::min<std::size_t>(max_size,
262 streambuf_.max_size() - streambuf_.size()));
263 if (bytes_available == 0)
265 handler_(ec, total_transferred_);
269 stream_.async_read_some(streambuf_.prepare(bytes_available), *this);
274 AsyncReadStream& stream_;
275 boost::asio::basic_streambuf<Allocator>& streambuf_;
276 std::size_t total_transferred_;
277 CompletionCondition completion_condition_;
278 ReadHandler handler_;
281 template <typename AsyncReadStream, typename Allocator,
282 typename CompletionCondition, typename ReadHandler>
283 inline void* asio_handler_allocate(std::size_t size,
284 read_streambuf_handler<AsyncReadStream, Allocator,
285 CompletionCondition, ReadHandler>* this_handler)
287 return boost_asio_handler_alloc_helpers::allocate(
288 size, &this_handler->handler_);
291 template <typename AsyncReadStream, typename Allocator,
292 typename CompletionCondition, typename ReadHandler>
293 inline void asio_handler_deallocate(void* pointer, std::size_t size,
294 read_streambuf_handler<AsyncReadStream, Allocator,
295 CompletionCondition, ReadHandler>* this_handler)
297 boost_asio_handler_alloc_helpers::deallocate(
298 pointer, size, &this_handler->handler_);
301 template <typename Function, typename AsyncReadStream,
302 typename Allocator, typename CompletionCondition, typename ReadHandler>
303 inline void asio_handler_invoke(const Function& function,
304 read_streambuf_handler<AsyncReadStream, Allocator,
305 CompletionCondition, ReadHandler>* this_handler)
307 boost_asio_handler_invoke_helpers::invoke(
308 function, &this_handler->handler_);
310 } // namespace detail
312 template <typename AsyncReadStream, typename Allocator,
313 typename CompletionCondition, typename ReadHandler>
314 inline void async_read(AsyncReadStream& s,
315 boost::asio::basic_streambuf<Allocator>& b,
316 CompletionCondition completion_condition, ReadHandler handler)
318 boost::system::error_code ec;
319 std::size_t total_transferred = 0;
320 std::size_t max_size = detail::adapt_completion_condition_result(
321 completion_condition(ec, total_transferred));
322 std::size_t bytes_available = std::min<std::size_t>(512,
323 std::min<std::size_t>(max_size, b.max_size() - b.size()));
324 if (bytes_available == 0)
326 s.get_io_service().post(detail::bind_handler(
327 handler, ec, total_transferred));
331 s.async_read_some(b.prepare(bytes_available),
332 detail::read_streambuf_handler<AsyncReadStream, Allocator,
333 CompletionCondition, ReadHandler>(
334 s, b, completion_condition, handler));
337 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
338 inline void async_read(AsyncReadStream& s,
339 boost::asio::basic_streambuf<Allocator>& b, ReadHandler handler)
341 async_read(s, b, transfer_all(), handler);
347 #include <boost/asio/detail/pop_options.hpp>
349 #endif // BOOST_ASIO_READ_IPP