1//
2// read_at.hpp
3// ~~~~~~~~~~~
4//
5// Copyright (c) 2003-2015 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_READ_AT_HPP
12#define BOOST_ASIO_READ_AT_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/basic_streambuf_fwd.hpp>
22#include <boost/asio/detail/cstdint.hpp>
23#include <boost/asio/error.hpp>
24
25#include <boost/asio/detail/push_options.hpp>
26
27namespace boost {
28namespace asio {
29
30/**
31 * @defgroup read_at boost::asio::read_at
32 *
33 * @brief Attempt to read a certain amount of data at the specified offset
34 * before returning.
35 */
36/*@{*/
37
38/// Attempt to read a certain amount of data at the specified offset before
39/// returning.
40/**
41 * This function is used to read a certain number of bytes of data from a
42 * random access device at the specified offset. The call will block until one
43 * of the following conditions is true:
44 *
45 * @li The supplied buffers are full. That is, the bytes transferred is equal to
46 * the sum of the buffer sizes.
47 *
48 * @li An error occurred.
49 *
50 * This operation is implemented in terms of zero or more calls to the device's
51 * read_some_at function.
52 *
53 * @param d The device from which the data is to be read. The type must support
54 * the SyncRandomAccessReadDevice concept.
55 *
56 * @param offset The offset at which the data will be read.
57 *
58 * @param buffers One or more buffers into which the data will be read. The sum
59 * of the buffer sizes indicates the maximum number of bytes to read from the
60 * device.
61 *
62 * @returns The number of bytes transferred.
63 *
64 * @throws boost::system::system_error Thrown on failure.
65 *
66 * @par Example
67 * To read into a single data buffer use the @ref buffer function as follows:
68 * @code boost::asio::read_at(d, 42, boost::asio::buffer(data, size)); @endcode
69 * See the @ref buffer documentation for information on reading into multiple
70 * buffers in one go, and how to use it with arrays, boost::array or
71 * std::vector.
72 *
73 * @note This overload is equivalent to calling:
74 * @code boost::asio::read_at(
75 * d, 42, buffers,
76 * boost::asio::transfer_all()); @endcode
77 */
78template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
79std::size_t read_at(SyncRandomAccessReadDevice& d,
80 uint64_t offset, const MutableBufferSequence& buffers);
81
82/// Attempt to read a certain amount of data at the specified offset before
83/// returning.
84/**
85 * This function is used to read a certain number of bytes of data from a
86 * random access device at the specified offset. The call will block until one
87 * of the following conditions is true:
88 *
89 * @li The supplied buffers are full. That is, the bytes transferred is equal to
90 * the sum of the buffer sizes.
91 *
92 * @li An error occurred.
93 *
94 * This operation is implemented in terms of zero or more calls to the device's
95 * read_some_at function.
96 *
97 * @param d The device from which the data is to be read. The type must support
98 * the SyncRandomAccessReadDevice concept.
99 *
100 * @param offset The offset at which the data will be read.
101 *
102 * @param buffers One or more buffers into which the data will be read. The sum
103 * of the buffer sizes indicates the maximum number of bytes to read from the
104 * device.
105 *
106 * @param ec Set to indicate what error occurred, if any.
107 *
108 * @returns The number of bytes transferred.
109 *
110 * @par Example
111 * To read into a single data buffer use the @ref buffer function as follows:
112 * @code boost::asio::read_at(d, 42,
113 * boost::asio::buffer(data, size), ec); @endcode
114 * See the @ref buffer documentation for information on reading into multiple
115 * buffers in one go, and how to use it with arrays, boost::array or
116 * std::vector.
117 *
118 * @note This overload is equivalent to calling:
119 * @code boost::asio::read_at(
120 * d, 42, buffers,
121 * boost::asio::transfer_all(), ec); @endcode
122 */
123template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
124std::size_t read_at(SyncRandomAccessReadDevice& d,
125 uint64_t offset, const MutableBufferSequence& buffers,
126 boost::system::error_code& ec);
127
128/// Attempt to read a certain amount of data at the specified offset before
129/// returning.
130/**
131 * This function is used to read a certain number of bytes of data from a
132 * random access device at the specified offset. The call will block until one
133 * of the following conditions is true:
134 *
135 * @li The supplied buffers are full. That is, the bytes transferred is equal to
136 * the sum of the buffer sizes.
137 *
138 * @li The completion_condition function object returns 0.
139 *
140 * This operation is implemented in terms of zero or more calls to the device's
141 * read_some_at function.
142 *
143 * @param d The device from which the data is to be read. The type must support
144 * the SyncRandomAccessReadDevice concept.
145 *
146 * @param offset The offset at which the data will be read.
147 *
148 * @param buffers One or more buffers into which the data will be read. The sum
149 * of the buffer sizes indicates the maximum number of bytes to read from the
150 * device.
151 *
152 * @param completion_condition The function object to be called to determine
153 * whether the read operation is complete. The signature of the function object
154 * must be:
155 * @code std::size_t completion_condition(
156 * // Result of latest read_some_at operation.
157 * const boost::system::error_code& error,
158 *
159 * // Number of bytes transferred so far.
160 * std::size_t bytes_transferred
161 * ); @endcode
162 * A return value of 0 indicates that the read operation is complete. A non-zero
163 * return value indicates the maximum number of bytes to be read on the next
164 * call to the device's read_some_at function.
165 *
166 * @returns The number of bytes transferred.
167 *
168 * @throws boost::system::system_error Thrown on failure.
169 *
170 * @par Example
171 * To read into a single data buffer use the @ref buffer function as follows:
172 * @code boost::asio::read_at(d, 42, boost::asio::buffer(data, size),
173 * boost::asio::transfer_at_least(32)); @endcode
174 * See the @ref buffer documentation for information on reading into multiple
175 * buffers in one go, and how to use it with arrays, boost::array or
176 * std::vector.
177 */
178template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
179 typename CompletionCondition>
180std::size_t read_at(SyncRandomAccessReadDevice& d,
181 uint64_t offset, const MutableBufferSequence& buffers,
182 CompletionCondition completion_condition);
183
184/// Attempt to read a certain amount of data at the specified offset before
185/// returning.
186/**
187 * This function is used to read a certain number of bytes of data from a
188 * random access device at the specified offset. The call will block until one
189 * of the following conditions is true:
190 *
191 * @li The supplied buffers are full. That is, the bytes transferred is equal to
192 * the sum of the buffer sizes.
193 *
194 * @li The completion_condition function object returns 0.
195 *
196 * This operation is implemented in terms of zero or more calls to the device's
197 * read_some_at function.
198 *
199 * @param d The device from which the data is to be read. The type must support
200 * the SyncRandomAccessReadDevice concept.
201 *
202 * @param offset The offset at which the data will be read.
203 *
204 * @param buffers One or more buffers into which the data will be read. The sum
205 * of the buffer sizes indicates the maximum number of bytes to read from the
206 * device.
207 *
208 * @param completion_condition The function object to be called to determine
209 * whether the read operation is complete. The signature of the function object
210 * must be:
211 * @code std::size_t completion_condition(
212 * // Result of latest read_some_at operation.
213 * const boost::system::error_code& error,
214 *
215 * // Number of bytes transferred so far.
216 * std::size_t bytes_transferred
217 * ); @endcode
218 * A return value of 0 indicates that the read operation is complete. A non-zero
219 * return value indicates the maximum number of bytes to be read on the next
220 * call to the device's read_some_at function.
221 *
222 * @param ec Set to indicate what error occurred, if any.
223 *
224 * @returns The number of bytes read. If an error occurs, returns the total
225 * number of bytes successfully transferred prior to the error.
226 */
227template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
228 typename CompletionCondition>
229std::size_t read_at(SyncRandomAccessReadDevice& d,
230 uint64_t offset, const MutableBufferSequence& buffers,
231 CompletionCondition completion_condition, boost::system::error_code& ec);
232
233#if !defined(BOOST_ASIO_NO_IOSTREAM)
234
235/// Attempt to read a certain amount of data at the specified offset before
236/// returning.
237/**
238 * This function is used to read a certain number of bytes of data from a
239 * random access device at the specified offset. The call will block until one
240 * of the following conditions is true:
241 *
242 * @li An error occurred.
243 *
244 * This operation is implemented in terms of zero or more calls to the device's
245 * read_some_at function.
246 *
247 * @param d The device from which the data is to be read. The type must support
248 * the SyncRandomAccessReadDevice concept.
249 *
250 * @param offset The offset at which the data will be read.
251 *
252 * @param b The basic_streambuf object into which the data will be read.
253 *
254 * @returns The number of bytes transferred.
255 *
256 * @throws boost::system::system_error Thrown on failure.
257 *
258 * @note This overload is equivalent to calling:
259 * @code boost::asio::read_at(
260 * d, 42, b,
261 * boost::asio::transfer_all()); @endcode
262 */
263template <typename SyncRandomAccessReadDevice, typename Allocator>
264std::size_t read_at(SyncRandomAccessReadDevice& d,
265 uint64_t offset, basic_streambuf<Allocator>& b);
266
267/// Attempt to read a certain amount of data at the specified offset before
268/// returning.
269/**
270 * This function is used to read a certain number of bytes of data from a
271 * random access device at the specified offset. The call will block until one
272 * of the following conditions is true:
273 *
274 * @li An error occurred.
275 *
276 * This operation is implemented in terms of zero or more calls to the device's
277 * read_some_at function.
278 *
279 * @param d The device from which the data is to be read. The type must support
280 * the SyncRandomAccessReadDevice concept.
281 *
282 * @param offset The offset at which the data will be read.
283 *
284 * @param b The basic_streambuf object into which the data will be read.
285 *
286 * @param ec Set to indicate what error occurred, if any.
287 *
288 * @returns The number of bytes transferred.
289 *
290 * @note This overload is equivalent to calling:
291 * @code boost::asio::read_at(
292 * d, 42, b,
293 * boost::asio::transfer_all(), ec); @endcode
294 */
295template <typename SyncRandomAccessReadDevice, typename Allocator>
296std::size_t read_at(SyncRandomAccessReadDevice& d,
297 uint64_t offset, basic_streambuf<Allocator>& b,
298 boost::system::error_code& ec);
299
300/// Attempt to read a certain amount of data at the specified offset before
301/// returning.
302/**
303 * This function is used to read a certain number of bytes of data from a
304 * random access device at the specified offset. The call will block until one
305 * of the following conditions is true:
306 *
307 * @li The completion_condition function object returns 0.
308 *
309 * This operation is implemented in terms of zero or more calls to the device's
310 * read_some_at function.
311 *
312 * @param d The device from which the data is to be read. The type must support
313 * the SyncRandomAccessReadDevice concept.
314 *
315 * @param offset The offset at which the data will be read.
316 *
317 * @param b The basic_streambuf object into which the data will be read.
318 *
319 * @param completion_condition The function object to be called to determine
320 * whether the read operation is complete. The signature of the function object
321 * must be:
322 * @code std::size_t completion_condition(
323 * // Result of latest read_some_at operation.
324 * const boost::system::error_code& error,
325 *
326 * // Number of bytes transferred so far.
327 * std::size_t bytes_transferred
328 * ); @endcode
329 * A return value of 0 indicates that the read operation is complete. A non-zero
330 * return value indicates the maximum number of bytes to be read on the next
331 * call to the device's read_some_at function.
332 *
333 * @returns The number of bytes transferred.
334 *
335 * @throws boost::system::system_error Thrown on failure.
336 */
337template <typename SyncRandomAccessReadDevice, typename Allocator,
338 typename CompletionCondition>
339std::size_t read_at(SyncRandomAccessReadDevice& d,
340 uint64_t offset, basic_streambuf<Allocator>& b,
341 CompletionCondition completion_condition);
342
343/// Attempt to read a certain amount of data at the specified offset before
344/// returning.
345/**
346 * This function is used to read a certain number of bytes of data from a
347 * random access device at the specified offset. The call will block until one
348 * of the following conditions is true:
349 *
350 * @li The completion_condition function object returns 0.
351 *
352 * This operation is implemented in terms of zero or more calls to the device's
353 * read_some_at function.
354 *
355 * @param d The device from which the data is to be read. The type must support
356 * the SyncRandomAccessReadDevice concept.
357 *
358 * @param offset The offset at which the data will be read.
359 *
360 * @param b The basic_streambuf object into which the data will be read.
361 *
362 * @param completion_condition The function object to be called to determine
363 * whether the read operation is complete. The signature of the function object
364 * must be:
365 * @code std::size_t completion_condition(
366 * // Result of latest read_some_at operation.
367 * const boost::system::error_code& error,
368 *
369 * // Number of bytes transferred so far.
370 * std::size_t bytes_transferred
371 * ); @endcode
372 * A return value of 0 indicates that the read operation is complete. A non-zero
373 * return value indicates the maximum number of bytes to be read on the next
374 * call to the device's read_some_at function.
375 *
376 * @param ec Set to indicate what error occurred, if any.
377 *
378 * @returns The number of bytes read. If an error occurs, returns the total
379 * number of bytes successfully transferred prior to the error.
380 */
381template <typename SyncRandomAccessReadDevice, typename Allocator,
382 typename CompletionCondition>
383std::size_t read_at(SyncRandomAccessReadDevice& d,
384 uint64_t offset, basic_streambuf<Allocator>& b,
385 CompletionCondition completion_condition, boost::system::error_code& ec);
386
387#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
388
389/*@}*/
390/**
391 * @defgroup async_read_at boost::asio::async_read_at
392 *
393 * @brief Start an asynchronous operation to read a certain amount of data at
394 * the specified offset.
395 */
396/*@{*/
397
398/// Start an asynchronous operation to read a certain amount of data at the
399/// specified offset.
400/**
401 * This function is used to asynchronously read a certain number of bytes of
402 * data from a random access device at the specified offset. The function call
403 * always returns immediately. The asynchronous operation will continue until
404 * one of the following conditions is true:
405 *
406 * @li The supplied buffers are full. That is, the bytes transferred is equal to
407 * the sum of the buffer sizes.
408 *
409 * @li An error occurred.
410 *
411 * This operation is implemented in terms of zero or more calls to the device's
412 * async_read_some_at function.
413 *
414 * @param d The device from which the data is to be read. The type must support
415 * the AsyncRandomAccessReadDevice concept.
416 *
417 * @param offset The offset at which the data will be read.
418 *
419 * @param buffers One or more buffers into which the data will be read. The sum
420 * of the buffer sizes indicates the maximum number of bytes to read from the
421 * device. Although the buffers object may be copied as necessary, ownership of
422 * the underlying memory blocks is retained by the caller, which must guarantee
423 * that they remain valid until the handler is called.
424 *
425 * @param handler The handler to be called when the read operation completes.
426 * Copies will be made of the handler as required. The function signature of the
427 * handler must be:
428 * @code void handler(
429 * // Result of operation.
430 * const boost::system::error_code& error,
431 *
432 * // Number of bytes copied into the buffers. If an error
433 * // occurred, this will be the number of bytes successfully
434 * // transferred prior to the error.
435 * std::size_t bytes_transferred
436 * ); @endcode
437 * Regardless of whether the asynchronous operation completes immediately or
438 * not, the handler will not be invoked from within this function. Invocation of
439 * the handler will be performed in a manner equivalent to using
440 * boost::asio::io_service::post().
441 *
442 * @par Example
443 * To read into a single data buffer use the @ref buffer function as follows:
444 * @code
445 * boost::asio::async_read_at(d, 42, boost::asio::buffer(data, size), handler);
446 * @endcode
447 * See the @ref buffer documentation for information on reading into multiple
448 * buffers in one go, and how to use it with arrays, boost::array or
449 * std::vector.
450 *
451 * @note This overload is equivalent to calling:
452 * @code boost::asio::async_read_at(
453 * d, 42, buffers,
454 * boost::asio::transfer_all(),
455 * handler); @endcode
456 */
457template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
458 typename ReadHandler>
459BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
460 void (boost::system::error_code, std::size_t))
461async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset,
462 const MutableBufferSequence& buffers,
463 BOOST_ASIO_MOVE_ARG(ReadHandler) handler);
464
465/// Start an asynchronous operation to read a certain amount of data at the
466/// specified offset.
467/**
468 * This function is used to asynchronously read a certain number of bytes of
469 * data from a random access device at the specified offset. The function call
470 * always returns immediately. The asynchronous operation will continue until
471 * one of the following conditions is true:
472 *
473 * @li The supplied buffers are full. That is, the bytes transferred is equal to
474 * the sum of the buffer sizes.
475 *
476 * @li The completion_condition function object returns 0.
477 *
478 * @param d The device from which the data is to be read. The type must support
479 * the AsyncRandomAccessReadDevice concept.
480 *
481 * @param offset The offset at which the data will be read.
482 *
483 * @param buffers One or more buffers into which the data will be read. The sum
484 * of the buffer sizes indicates the maximum number of bytes to read from the
485 * device. Although the buffers object may be copied as necessary, ownership of
486 * the underlying memory blocks is retained by the caller, which must guarantee
487 * that they remain valid until the handler is called.
488 *
489 * @param completion_condition The function object to be called to determine
490 * whether the read operation is complete. The signature of the function object
491 * must be:
492 * @code std::size_t completion_condition(
493 * // Result of latest async_read_some_at operation.
494 * const boost::system::error_code& error,
495 *
496 * // Number of bytes transferred so far.
497 * std::size_t bytes_transferred
498 * ); @endcode
499 * A return value of 0 indicates that the read operation is complete. A non-zero
500 * return value indicates the maximum number of bytes to be read on the next
501 * call to the device's async_read_some_at function.
502 *
503 * @param handler The handler to be called when the read operation completes.
504 * Copies will be made of the handler as required. The function signature of the
505 * handler must be:
506 * @code void handler(
507 * // Result of operation.
508 * const boost::system::error_code& error,
509 *
510 * // Number of bytes copied into the buffers. If an error
511 * // occurred, this will be the number of bytes successfully
512 * // transferred prior to the error.
513 * std::size_t bytes_transferred
514 * ); @endcode
515 * Regardless of whether the asynchronous operation completes immediately or
516 * not, the handler will not be invoked from within this function. Invocation of
517 * the handler will be performed in a manner equivalent to using
518 * boost::asio::io_service::post().
519 *
520 * @par Example
521 * To read into a single data buffer use the @ref buffer function as follows:
522 * @code boost::asio::async_read_at(d, 42,
523 * boost::asio::buffer(data, size),
524 * boost::asio::transfer_at_least(32),
525 * handler); @endcode
526 * See the @ref buffer documentation for information on reading into multiple
527 * buffers in one go, and how to use it with arrays, boost::array or
528 * std::vector.
529 */
530template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
531 typename CompletionCondition, typename ReadHandler>
532BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
533 void (boost::system::error_code, std::size_t))
534async_read_at(AsyncRandomAccessReadDevice& d,
535 uint64_t offset, const MutableBufferSequence& buffers,
536 CompletionCondition completion_condition,
537 BOOST_ASIO_MOVE_ARG(ReadHandler) handler);
538
539#if !defined(BOOST_ASIO_NO_IOSTREAM)
540
541/// Start an asynchronous operation to read a certain amount of data at the
542/// specified offset.
543/**
544 * This function is used to asynchronously read a certain number of bytes of
545 * data from a random access device at the specified offset. The function call
546 * always returns immediately. The asynchronous operation will continue until
547 * one of the following conditions is true:
548 *
549 * @li An error occurred.
550 *
551 * This operation is implemented in terms of zero or more calls to the device's
552 * async_read_some_at function.
553 *
554 * @param d The device from which the data is to be read. The type must support
555 * the AsyncRandomAccessReadDevice concept.
556 *
557 * @param offset The offset at which the data will be read.
558 *
559 * @param b A basic_streambuf object into which the data will be read. Ownership
560 * of the streambuf is retained by the caller, which must guarantee that it
561 * remains valid until the handler is called.
562 *
563 * @param handler The handler to be called when the read operation completes.
564 * Copies will be made of the handler as required. The function signature of the
565 * handler must be:
566 * @code void handler(
567 * // Result of operation.
568 * const boost::system::error_code& error,
569 *
570 * // Number of bytes copied into the buffers. If an error
571 * // occurred, this will be the number of bytes successfully
572 * // transferred prior to the error.
573 * std::size_t bytes_transferred
574 * ); @endcode
575 * Regardless of whether the asynchronous operation completes immediately or
576 * not, the handler will not be invoked from within this function. Invocation of
577 * the handler will be performed in a manner equivalent to using
578 * boost::asio::io_service::post().
579 *
580 * @note This overload is equivalent to calling:
581 * @code boost::asio::async_read_at(
582 * d, 42, b,
583 * boost::asio::transfer_all(),
584 * handler); @endcode
585 */
586template <typename AsyncRandomAccessReadDevice, typename Allocator,
587 typename ReadHandler>
588BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
589 void (boost::system::error_code, std::size_t))
590async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset,
591 basic_streambuf<Allocator>& b, BOOST_ASIO_MOVE_ARG(ReadHandler) handler);
592
593/// Start an asynchronous operation to read a certain amount of data at the
594/// specified offset.
595/**
596 * This function is used to asynchronously read a certain number of bytes of
597 * data from a random access device at the specified offset. The function call
598 * always returns immediately. The asynchronous operation will continue until
599 * one of the following conditions is true:
600 *
601 * @li The completion_condition function object returns 0.
602 *
603 * This operation is implemented in terms of zero or more calls to the device's
604 * async_read_some_at function.
605 *
606 * @param d The device from which the data is to be read. The type must support
607 * the AsyncRandomAccessReadDevice concept.
608 *
609 * @param offset The offset at which the data will be read.
610 *
611 * @param b A basic_streambuf object into which the data will be read. Ownership
612 * of the streambuf is retained by the caller, which must guarantee that it
613 * remains valid until the handler is called.
614 *
615 * @param completion_condition The function object to be called to determine
616 * whether the read operation is complete. The signature of the function object
617 * must be:
618 * @code std::size_t completion_condition(
619 * // Result of latest async_read_some_at operation.
620 * const boost::system::error_code& error,
621 *
622 * // Number of bytes transferred so far.
623 * std::size_t bytes_transferred
624 * ); @endcode
625 * A return value of 0 indicates that the read operation is complete. A non-zero
626 * return value indicates the maximum number of bytes to be read on the next
627 * call to the device's async_read_some_at function.
628 *
629 * @param handler The handler to be called when the read operation completes.
630 * Copies will be made of the handler as required. The function signature of the
631 * handler must be:
632 * @code void handler(
633 * // Result of operation.
634 * const boost::system::error_code& error,
635 *
636 * // Number of bytes copied into the buffers. If an error
637 * // occurred, this will be the number of bytes successfully
638 * // transferred prior to the error.
639 * std::size_t bytes_transferred
640 * ); @endcode
641 * Regardless of whether the asynchronous operation completes immediately or
642 * not, the handler will not be invoked from within this function. Invocation of
643 * the handler will be performed in a manner equivalent to using
644 * boost::asio::io_service::post().
645 */
646template <typename AsyncRandomAccessReadDevice, typename Allocator,
647 typename CompletionCondition, typename ReadHandler>
648BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
649 void (boost::system::error_code, std::size_t))
650async_read_at(AsyncRandomAccessReadDevice& d,
651 uint64_t offset, basic_streambuf<Allocator>& b,
652 CompletionCondition completion_condition,
653 BOOST_ASIO_MOVE_ARG(ReadHandler) handler);
654
655#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
656
657/*@}*/
658
659} // namespace asio
660} // namespace boost
661
662#include <boost/asio/detail/pop_options.hpp>
663
664#include <boost/asio/impl/read_at.hpp>
665
666#endif // BOOST_ASIO_READ_AT_HPP
667