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_AT_IPP
12 #define BOOST_ASIO_READ_AT_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 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())
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)));
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;
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;
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;
131 template <typename AsyncRandomAccessReadDevice,
132 typename MutableBufferSequence, typename CompletionCondition,
133 typename ReadHandler>
134 class read_at_handler
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)
146 total_transferred_(0),
147 completion_condition_(completion_condition),
152 void operator()(const boost::system::error_code& ec,
153 std::size_t bytes_transferred)
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())
161 handler_(ec, total_transferred_);
165 stream_.async_read_some_at(
166 offset_ + total_transferred_, buffers_, *this);
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_;
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)
186 return boost_asio_handler_alloc_helpers::allocate(
187 size, &this_handler->handler_);
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)
197 boost_asio_handler_alloc_helpers::deallocate(
198 pointer, size, &this_handler->handler_);
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)
208 boost_asio_handler_invoke_helpers::invoke(
209 function, &this_handler->handler_);
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())
228 d.get_io_service().post(detail::bind_handler(
229 handler, ec, total_transferred));
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,
245 async_read_at(d, offset, buffers, transfer_all(), handler);
250 template <typename AsyncRandomAccessReadDevice, typename Allocator,
251 typename CompletionCondition, typename ReadHandler>
252 class read_at_streambuf_handler
255 read_at_streambuf_handler(AsyncRandomAccessReadDevice& stream,
256 boost::uint64_t offset, basic_streambuf<Allocator>& streambuf,
257 CompletionCondition completion_condition, ReadHandler handler)
260 streambuf_(streambuf),
261 total_transferred_(0),
262 completion_condition_(completion_condition),
267 void operator()(const boost::system::error_code& ec,
268 std::size_t bytes_transferred)
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)
279 handler_(ec, total_transferred_);
283 stream_.async_read_some_at(offset_ + total_transferred_,
284 streambuf_.prepare(bytes_available), *this);
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_;
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)
303 return boost_asio_handler_alloc_helpers::allocate(
304 size, &this_handler->handler_);
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)
313 boost_asio_handler_alloc_helpers::deallocate(
314 pointer, size, &this_handler->handler_);
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)
323 boost_asio_handler_invoke_helpers::invoke(
324 function, &this_handler->handler_);
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)
342 d.get_io_service().post(detail::bind_handler(
343 handler, ec, total_transferred));
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,
359 async_read_at(d, offset, b, transfer_all(), handler);
365 #include <boost/asio/detail/pop_options.hpp>
367 #endif // BOOST_ASIO_READ_AT_IPP