fix doc example typo
[boost.git] / boost / asio / impl / read.ipp
blob453f69761ce3187c72d0fd86dbf10477146ea529
1 //
2 // read.ipp
3 // ~~~~~~~~
4 //
5 // Copyright (c) 2003-2008 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 //
11 #ifndef BOOST_ASIO_READ_IPP
12 #define BOOST_ASIO_READ_IPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/push_options.hpp>
20 #include <boost/asio/detail/push_options.hpp>
21 #include <algorithm>
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>
33 namespace boost {
34 namespace asio {
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())
48   {
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)));
54   }
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)
91   {
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()));
99   }
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;
125 namespace detail
127   template <typename AsyncReadStream, typename MutableBufferSequence,
128       typename CompletionCondition, typename ReadHandler>
129   class read_handler
130   {
131   public:
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)
137       : stream_(stream),
138         buffers_(buffers),
139         total_transferred_(0),
140         completion_condition_(completion_condition),
141         handler_(handler)
142     {
143     }
145     void operator()(const boost::system::error_code& ec,
146         std::size_t bytes_transferred)
147     {
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())
153       {
154         handler_(ec, total_transferred_);
155       }
156       else
157       {
158         stream_.async_read_some(buffers_, *this);
159       }
160     }
162   //private:
163     AsyncReadStream& stream_;
164     buffers_type buffers_;
165     std::size_t total_transferred_;
166     CompletionCondition completion_condition_;
167     ReadHandler handler_;
168   };
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)
175   {
176     return boost_asio_handler_alloc_helpers::allocate(
177         size, &this_handler->handler_);
178   }
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)
185   {
186     boost_asio_handler_alloc_helpers::deallocate(
187         pointer, size, &this_handler->handler_);
188   }
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)
196   {
197     boost_asio_handler_invoke_helpers::invoke(
198         function, &this_handler->handler_);
199   }
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())
215   {
216     s.get_io_service().post(detail::bind_handler(
217           handler, ec, total_transferred));
218     return;
219   }
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,
230     ReadHandler handler)
232   async_read(s, buffers, transfer_all(), handler);
235 namespace detail
237   template <typename AsyncReadStream, typename Allocator,
238       typename CompletionCondition, typename ReadHandler>
239   class read_streambuf_handler
240   {
241   public:
242     read_streambuf_handler(AsyncReadStream& stream,
243         basic_streambuf<Allocator>& streambuf,
244         CompletionCondition completion_condition, ReadHandler handler)
245       : stream_(stream),
246         streambuf_(streambuf),
247         total_transferred_(0),
248         completion_condition_(completion_condition),
249         handler_(handler)
250     {
251     }
253     void operator()(const boost::system::error_code& ec,
254         std::size_t bytes_transferred)
255     {
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)
264       {
265         handler_(ec, total_transferred_);
266       }
267       else
268       {
269         stream_.async_read_some(streambuf_.prepare(bytes_available), *this);
270       }
271     }
273   //private:
274     AsyncReadStream& stream_;
275     boost::asio::basic_streambuf<Allocator>& streambuf_;
276     std::size_t total_transferred_;
277     CompletionCondition completion_condition_;
278     ReadHandler handler_;
279   };
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)
286   {
287     return boost_asio_handler_alloc_helpers::allocate(
288         size, &this_handler->handler_);
289   }
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)
296   {
297     boost_asio_handler_alloc_helpers::deallocate(
298         pointer, size, &this_handler->handler_);
299   }
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)
306   {
307     boost_asio_handler_invoke_helpers::invoke(
308         function, &this_handler->handler_);
309   }
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)
325   {
326     s.get_io_service().post(detail::bind_handler(
327           handler, ec, total_transferred));
328     return;
329   }
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);
344 } // namespace asio
345 } // namespace boost
347 #include <boost/asio/detail/pop_options.hpp>
349 #endif // BOOST_ASIO_READ_IPP