fix doc example typo
[boost.git] / boost / asio / impl / read_at.ipp
blobbf8a36d0bba076c42e0cca0a708881811eca4ff0
1 //
2 // read_at.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_AT_IPP
12 #define BOOST_ASIO_READ_AT_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 SyncRandomAccessReadDevice, typename MutableBufferSequence,
37     typename CompletionCondition>
38 std::size_t read_at(SyncRandomAccessReadDevice& d,
39     boost::uint64_t offset, const MutableBufferSequence& buffers,
40     CompletionCondition completion_condition, boost::system::error_code& ec)
42   ec = boost::system::error_code();
43   boost::asio::detail::consuming_buffers<
44     mutable_buffer, MutableBufferSequence> tmp(buffers);
45   std::size_t total_transferred = 0;
46   tmp.set_max_size(detail::adapt_completion_condition_result(
47         completion_condition(ec, total_transferred)));
48   while (tmp.begin() != tmp.end())
49   {
50     std::size_t bytes_transferred = d.read_some_at(
51         offset + total_transferred, tmp, ec);
52     tmp.consume(bytes_transferred);
53     total_transferred += bytes_transferred;
54     tmp.set_max_size(detail::adapt_completion_condition_result(
55           completion_condition(ec, total_transferred)));
56   }
57   return total_transferred;
60 template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
61 inline std::size_t read_at(SyncRandomAccessReadDevice& d,
62     boost::uint64_t offset, const MutableBufferSequence& buffers)
64   boost::system::error_code ec;
65   std::size_t bytes_transferred = read_at(
66       d, offset, buffers, transfer_all(), ec);
67   boost::asio::detail::throw_error(ec);
68   return bytes_transferred;
71 template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
72     typename CompletionCondition>
73 inline std::size_t read_at(SyncRandomAccessReadDevice& d,
74     boost::uint64_t offset, const MutableBufferSequence& buffers,
75     CompletionCondition completion_condition)
77   boost::system::error_code ec;
78   std::size_t bytes_transferred = read_at(
79       d, offset, buffers, completion_condition, ec);
80   boost::asio::detail::throw_error(ec);
81   return bytes_transferred;
84 template <typename SyncRandomAccessReadDevice, typename Allocator,
85     typename CompletionCondition>
86 std::size_t read_at(SyncRandomAccessReadDevice& d,
87     boost::uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
88     CompletionCondition completion_condition, boost::system::error_code& ec)
90   std::size_t total_transferred = 0;
91   for (;;)
92   {
93     std::size_t bytes_available =
94       std::min<std::size_t>(512, b.max_size() - b.size());
95     std::size_t bytes_transferred = d.read_some_at(
96         offset + total_transferred, b.prepare(bytes_available), ec);
97     b.commit(bytes_transferred);
98     total_transferred += bytes_transferred;
99     if (b.size() == b.max_size()
100         || completion_condition(ec, total_transferred))
101       return total_transferred;
102   }
105 template <typename SyncRandomAccessReadDevice, typename Allocator>
106 inline std::size_t read_at(SyncRandomAccessReadDevice& d,
107     boost::uint64_t offset, boost::asio::basic_streambuf<Allocator>& b)
109   boost::system::error_code ec;
110   std::size_t bytes_transferred = read_at(
111       d, offset, b, transfer_all(), ec);
112   boost::asio::detail::throw_error(ec);
113   return bytes_transferred;
116 template <typename SyncRandomAccessReadDevice, typename Allocator,
117     typename CompletionCondition>
118 inline std::size_t read_at(SyncRandomAccessReadDevice& d,
119     boost::uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
120     CompletionCondition completion_condition)
122   boost::system::error_code ec;
123   std::size_t bytes_transferred = read_at(
124       d, offset, b, completion_condition, ec);
125   boost::asio::detail::throw_error(ec);
126   return bytes_transferred;
129 namespace detail
131   template <typename AsyncRandomAccessReadDevice,
132       typename MutableBufferSequence, typename CompletionCondition,
133       typename ReadHandler>
134   class read_at_handler
135   {
136   public:
137     typedef boost::asio::detail::consuming_buffers<
138       mutable_buffer, MutableBufferSequence> buffers_type;
140     read_at_handler(AsyncRandomAccessReadDevice& stream,
141         boost::uint64_t offset, const buffers_type& buffers,
142         CompletionCondition completion_condition, ReadHandler handler)
143       : stream_(stream),
144         offset_(offset),
145         buffers_(buffers),
146         total_transferred_(0),
147         completion_condition_(completion_condition),
148         handler_(handler)
149     {
150     }
152     void operator()(const boost::system::error_code& ec,
153         std::size_t bytes_transferred)
154     {
155       total_transferred_ += bytes_transferred;
156       buffers_.consume(bytes_transferred);
157       buffers_.set_max_size(detail::adapt_completion_condition_result(
158             completion_condition_(ec, total_transferred_)));
159       if (buffers_.begin() == buffers_.end())
160       {
161         handler_(ec, total_transferred_);
162       }
163       else
164       {
165         stream_.async_read_some_at(
166             offset_ + total_transferred_, buffers_, *this);
167       }
168     }
170   //private:
171     AsyncRandomAccessReadDevice& stream_;
172     boost::uint64_t offset_;
173     buffers_type buffers_;
174     std::size_t total_transferred_;
175     CompletionCondition completion_condition_;
176     ReadHandler handler_;
177   };
179   template <typename AsyncRandomAccessReadDevice,
180       typename MutableBufferSequence, typename CompletionCondition,
181       typename ReadHandler>
182   inline void* asio_handler_allocate(std::size_t size,
183       read_at_handler<AsyncRandomAccessReadDevice, MutableBufferSequence,
184         CompletionCondition, ReadHandler>* this_handler)
185   {
186     return boost_asio_handler_alloc_helpers::allocate(
187         size, &this_handler->handler_);
188   }
190   template <typename AsyncRandomAccessReadDevice,
191       typename MutableBufferSequence, typename CompletionCondition,
192       typename ReadHandler>
193   inline void asio_handler_deallocate(void* pointer, std::size_t size,
194       read_at_handler<AsyncRandomAccessReadDevice, MutableBufferSequence,
195         CompletionCondition, ReadHandler>* this_handler)
196   {
197     boost_asio_handler_alloc_helpers::deallocate(
198         pointer, size, &this_handler->handler_);
199   }
201   template <typename Function, typename AsyncRandomAccessReadDevice,
202       typename MutableBufferSequence, typename CompletionCondition,
203       typename ReadHandler>
204   inline void asio_handler_invoke(const Function& function,
205       read_at_handler<AsyncRandomAccessReadDevice, MutableBufferSequence,
206         CompletionCondition, ReadHandler>* this_handler)
207   {
208     boost_asio_handler_invoke_helpers::invoke(
209         function, &this_handler->handler_);
210   }
211 } // namespace detail
213 template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
214     typename CompletionCondition, typename ReadHandler>
215 inline void async_read_at(AsyncRandomAccessReadDevice& d,
216     boost::uint64_t offset, const MutableBufferSequence& buffers,
217     CompletionCondition completion_condition, ReadHandler handler)
219   boost::asio::detail::consuming_buffers<
220     mutable_buffer, MutableBufferSequence> tmp(buffers);
222   boost::system::error_code ec;
223   std::size_t total_transferred = 0;
224   tmp.set_max_size(detail::adapt_completion_condition_result(
225         completion_condition(ec, total_transferred)));
226   if (tmp.begin() == tmp.end())
227   {
228     d.get_io_service().post(detail::bind_handler(
229           handler, ec, total_transferred));
230     return;
231   }
233   d.async_read_some_at(offset, tmp,
234       detail::read_at_handler<AsyncRandomAccessReadDevice,
235         MutableBufferSequence, CompletionCondition, ReadHandler>(
236           d, offset, tmp, completion_condition, handler));
239 template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
240     typename ReadHandler>
241 inline void async_read_at(AsyncRandomAccessReadDevice& d,
242     boost::uint64_t offset, const MutableBufferSequence& buffers,
243     ReadHandler handler)
245   async_read_at(d, offset, buffers, transfer_all(), handler);
248 namespace detail
250   template <typename AsyncRandomAccessReadDevice, typename Allocator,
251       typename CompletionCondition, typename ReadHandler>
252   class read_at_streambuf_handler
253   {
254   public:
255     read_at_streambuf_handler(AsyncRandomAccessReadDevice& stream,
256         boost::uint64_t offset, basic_streambuf<Allocator>& streambuf,
257         CompletionCondition completion_condition, ReadHandler handler)
258       : stream_(stream),
259         offset_(offset),
260         streambuf_(streambuf),
261         total_transferred_(0),
262         completion_condition_(completion_condition),
263         handler_(handler)
264     {
265     }
267     void operator()(const boost::system::error_code& ec,
268         std::size_t bytes_transferred)
269     {
270       total_transferred_ += bytes_transferred;
271       streambuf_.commit(bytes_transferred);
272       std::size_t max_size = detail::adapt_completion_condition_result(
273             completion_condition_(ec, total_transferred_));
274       std::size_t bytes_available = std::min<std::size_t>(512,
275           std::min<std::size_t>(max_size,
276             streambuf_.max_size() - streambuf_.size()));
277       if (bytes_available == 0)
278       {
279         handler_(ec, total_transferred_);
280       }
281       else
282       {
283         stream_.async_read_some_at(offset_ + total_transferred_,
284             streambuf_.prepare(bytes_available), *this);
285       }
286     }
288   //private:
289     AsyncRandomAccessReadDevice& stream_;
290     boost::uint64_t offset_;
291     boost::asio::basic_streambuf<Allocator>& streambuf_;
292     std::size_t total_transferred_;
293     CompletionCondition completion_condition_;
294     ReadHandler handler_;
295   };
297   template <typename AsyncRandomAccessReadDevice, typename Allocator,
298       typename CompletionCondition, typename ReadHandler>
299   inline void* asio_handler_allocate(std::size_t size,
300       read_at_streambuf_handler<AsyncRandomAccessReadDevice, Allocator,
301         CompletionCondition, ReadHandler>* this_handler)
302   {
303     return boost_asio_handler_alloc_helpers::allocate(
304         size, &this_handler->handler_);
305   }
307   template <typename AsyncRandomAccessReadDevice, typename Allocator,
308       typename CompletionCondition, typename ReadHandler>
309   inline void asio_handler_deallocate(void* pointer, std::size_t size,
310       read_at_streambuf_handler<AsyncRandomAccessReadDevice, Allocator,
311         CompletionCondition, ReadHandler>* this_handler)
312   {
313     boost_asio_handler_alloc_helpers::deallocate(
314         pointer, size, &this_handler->handler_);
315   }
317   template <typename Function, typename AsyncRandomAccessReadDevice,
318       typename Allocator, typename CompletionCondition, typename ReadHandler>
319   inline void asio_handler_invoke(const Function& function,
320       read_at_streambuf_handler<AsyncRandomAccessReadDevice, Allocator,
321         CompletionCondition, ReadHandler>* this_handler)
322   {
323     boost_asio_handler_invoke_helpers::invoke(
324         function, &this_handler->handler_);
325   }
326 } // namespace detail
328 template <typename AsyncRandomAccessReadDevice, typename Allocator,
329     typename CompletionCondition, typename ReadHandler>
330 inline void async_read_at(AsyncRandomAccessReadDevice& d,
331     boost::uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
332     CompletionCondition completion_condition, ReadHandler handler)
334   boost::system::error_code ec;
335   std::size_t total_transferred = 0;
336   std::size_t max_size = detail::adapt_completion_condition_result(
337         completion_condition(ec, total_transferred));
338   std::size_t bytes_available = std::min<std::size_t>(512,
339       std::min<std::size_t>(max_size, b.max_size() - b.size()));
340   if (bytes_available == 0)
341   {
342     d.get_io_service().post(detail::bind_handler(
343           handler, ec, total_transferred));
344     return;
345   }
347   d.async_read_some_at(offset, b.prepare(bytes_available),
348       detail::read_at_streambuf_handler<AsyncRandomAccessReadDevice, Allocator,
349         CompletionCondition, ReadHandler>(
350           d, offset, b, completion_condition, handler));
353 template <typename AsyncRandomAccessReadDevice, typename Allocator,
354     typename ReadHandler>
355 inline void async_read_at(AsyncRandomAccessReadDevice& d,
356     boost::uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
357     ReadHandler handler)
359   async_read_at(d, offset, b, transfer_all(), handler);
362 } // namespace asio
363 } // namespace boost
365 #include <boost/asio/detail/pop_options.hpp>
367 #endif // BOOST_ASIO_READ_AT_IPP