Statistics
| Revision:

root / tmp / org.txm.statsengine.r.core.win32 / res / win32 / library / BH / include / boost / asio / impl / read_at.hpp @ 2486

History | View | Annotate | Download (29.1 kB)

1
//
2
// impl/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_IMPL_READ_AT_HPP
12
#define BOOST_ASIO_IMPL_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 <algorithm>
19
#include <boost/asio/buffer.hpp>
20
#include <boost/asio/completion_condition.hpp>
21
#include <boost/asio/detail/array_fwd.hpp>
22
#include <boost/asio/detail/base_from_completion_cond.hpp>
23
#include <boost/asio/detail/bind_handler.hpp>
24
#include <boost/asio/detail/consuming_buffers.hpp>
25
#include <boost/asio/detail/dependent_type.hpp>
26
#include <boost/asio/detail/handler_alloc_helpers.hpp>
27
#include <boost/asio/detail/handler_cont_helpers.hpp>
28
#include <boost/asio/detail/handler_invoke_helpers.hpp>
29
#include <boost/asio/detail/handler_type_requirements.hpp>
30
#include <boost/asio/detail/throw_error.hpp>
31
#include <boost/asio/error.hpp>
32

    
33
#include <boost/asio/detail/push_options.hpp>
34

    
35
namespace boost {
36
namespace asio {
37

    
38
template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
39
    typename CompletionCondition>
40
std::size_t read_at(SyncRandomAccessReadDevice& d,
41
    uint64_t offset, const MutableBufferSequence& buffers,
42
    CompletionCondition completion_condition, boost::system::error_code& ec)
43
{
44
  ec = boost::system::error_code();
45
  boost::asio::detail::consuming_buffers<
46
    mutable_buffer, MutableBufferSequence> tmp(buffers);
47
  std::size_t total_transferred = 0;
48
  tmp.prepare(detail::adapt_completion_condition_result(
49
        completion_condition(ec, total_transferred)));
50
  while (tmp.begin() != tmp.end())
51
  {
52
    std::size_t bytes_transferred = d.read_some_at(
53
        offset + total_transferred, tmp, ec);
54
    tmp.consume(bytes_transferred);
55
    total_transferred += bytes_transferred;
56
    tmp.prepare(detail::adapt_completion_condition_result(
57
          completion_condition(ec, total_transferred)));
58
  }
59
  return total_transferred;
60
}
61

    
62
template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
63
inline std::size_t read_at(SyncRandomAccessReadDevice& d,
64
    uint64_t offset, const MutableBufferSequence& buffers)
65
{
66
  boost::system::error_code ec;
67
  std::size_t bytes_transferred = read_at(
68
      d, offset, buffers, transfer_all(), ec);
69
  boost::asio::detail::throw_error(ec, "read_at");
70
  return bytes_transferred;
71
}
72

    
73
template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
74
inline std::size_t read_at(SyncRandomAccessReadDevice& d,
75
    uint64_t offset, const MutableBufferSequence& buffers,
76
    boost::system::error_code& ec)
77
{
78
  return read_at(d, offset, buffers, transfer_all(), ec);
79
}
80

    
81
template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
82
    typename CompletionCondition>
83
inline std::size_t read_at(SyncRandomAccessReadDevice& d,
84
    uint64_t offset, const MutableBufferSequence& buffers,
85
    CompletionCondition completion_condition)
86
{
87
  boost::system::error_code ec;
88
  std::size_t bytes_transferred = read_at(
89
      d, offset, buffers, completion_condition, ec);
90
  boost::asio::detail::throw_error(ec, "read_at");
91
  return bytes_transferred;
92
}
93

    
94
#if !defined(BOOST_ASIO_NO_IOSTREAM)
95

    
96
template <typename SyncRandomAccessReadDevice, typename Allocator,
97
    typename CompletionCondition>
98
std::size_t read_at(SyncRandomAccessReadDevice& d,
99
    uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
100
    CompletionCondition completion_condition, boost::system::error_code& ec)
101
{
102
  ec = boost::system::error_code();
103
  std::size_t total_transferred = 0;
104
  std::size_t max_size = detail::adapt_completion_condition_result(
105
        completion_condition(ec, total_transferred));
106
  std::size_t bytes_available = read_size_helper(b, max_size);
107
  while (bytes_available > 0)
108
  {
109
    std::size_t bytes_transferred = d.read_some_at(
110
        offset + total_transferred, b.prepare(bytes_available), ec);
111
    b.commit(bytes_transferred);
112
    total_transferred += bytes_transferred;
113
    max_size = detail::adapt_completion_condition_result(
114
          completion_condition(ec, total_transferred));
115
    bytes_available = read_size_helper(b, max_size);
116
  }
117
  return total_transferred;
118
}
119

    
120
template <typename SyncRandomAccessReadDevice, typename Allocator>
121
inline std::size_t read_at(SyncRandomAccessReadDevice& d,
122
    uint64_t offset, boost::asio::basic_streambuf<Allocator>& b)
123
{
124
  boost::system::error_code ec;
125
  std::size_t bytes_transferred = read_at(
126
      d, offset, b, transfer_all(), ec);
127
  boost::asio::detail::throw_error(ec, "read_at");
128
  return bytes_transferred;
129
}
130

    
131
template <typename SyncRandomAccessReadDevice, typename Allocator>
132
inline std::size_t read_at(SyncRandomAccessReadDevice& d,
133
    uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
134
    boost::system::error_code& ec)
135
{
136
  return read_at(d, offset, b, transfer_all(), ec);
137
}
138

    
139
template <typename SyncRandomAccessReadDevice, typename Allocator,
140
    typename CompletionCondition>
141
inline std::size_t read_at(SyncRandomAccessReadDevice& d,
142
    uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
143
    CompletionCondition completion_condition)
144
{
145
  boost::system::error_code ec;
146
  std::size_t bytes_transferred = read_at(
147
      d, offset, b, completion_condition, ec);
148
  boost::asio::detail::throw_error(ec, "read_at");
149
  return bytes_transferred;
150
}
151

    
152
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
153

    
154
namespace detail
155
{
156
  template <typename AsyncRandomAccessReadDevice,
157
      typename MutableBufferSequence, typename CompletionCondition,
158
      typename ReadHandler>
159
  class read_at_op
160
    : detail::base_from_completion_cond<CompletionCondition>
161
  {
162
  public:
163
    read_at_op(AsyncRandomAccessReadDevice& device,
164
        uint64_t offset, const MutableBufferSequence& buffers,
165
        CompletionCondition completion_condition, ReadHandler& handler)
166
      : detail::base_from_completion_cond<
167
          CompletionCondition>(completion_condition),
168
        device_(device),
169
        offset_(offset),
170
        buffers_(buffers),
171
        start_(0),
172
        total_transferred_(0),
173
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
174
    {
175
    }
176

    
177
#if defined(BOOST_ASIO_HAS_MOVE)
178
    read_at_op(const read_at_op& other)
179
      : detail::base_from_completion_cond<CompletionCondition>(other),
180
        device_(other.device_),
181
        offset_(other.offset_),
182
        buffers_(other.buffers_),
183
        start_(other.start_),
184
        total_transferred_(other.total_transferred_),
185
        handler_(other.handler_)
186
    {
187
    }
188

    
189
    read_at_op(read_at_op&& other)
190
      : detail::base_from_completion_cond<CompletionCondition>(other),
191
        device_(other.device_),
192
        offset_(other.offset_),
193
        buffers_(other.buffers_),
194
        start_(other.start_),
195
        total_transferred_(other.total_transferred_),
196
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
197
    {
198
    }
199
#endif // defined(BOOST_ASIO_HAS_MOVE)
200

    
201
    void operator()(const boost::system::error_code& ec,
202
        std::size_t bytes_transferred, int start = 0)
203
    {
204
      switch (start_ = start)
205
      {
206
        case 1:
207
        buffers_.prepare(this->check_for_completion(ec, total_transferred_));
208
        for (;;)
209
        {
210
          device_.async_read_some_at(offset_ + total_transferred_,
211
              buffers_, BOOST_ASIO_MOVE_CAST(read_at_op)(*this));
212
          return; default:
213
          total_transferred_ += bytes_transferred;
214
          buffers_.consume(bytes_transferred);
215
          buffers_.prepare(this->check_for_completion(ec, total_transferred_));
216
          if ((!ec && bytes_transferred == 0)
217
              || buffers_.begin() == buffers_.end())
218
            break;
219
        }
220

    
221
        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
222
      }
223
    }
224

    
225
  //private:
226
    AsyncRandomAccessReadDevice& device_;
227
    uint64_t offset_;
228
    boost::asio::detail::consuming_buffers<
229
      mutable_buffer, MutableBufferSequence> buffers_;
230
    int start_;
231
    std::size_t total_transferred_;
232
    ReadHandler handler_;
233
  };
234

    
235
  template <typename AsyncRandomAccessReadDevice,
236
      typename CompletionCondition, typename ReadHandler>
237
  class read_at_op<AsyncRandomAccessReadDevice,
238
      boost::asio::mutable_buffers_1, CompletionCondition, ReadHandler>
239
    : detail::base_from_completion_cond<CompletionCondition>
240
  {
241
  public:
242
    read_at_op(AsyncRandomAccessReadDevice& device,
243
        uint64_t offset, const boost::asio::mutable_buffers_1& buffers,
244
        CompletionCondition completion_condition, ReadHandler& handler)
245
      : detail::base_from_completion_cond<
246
          CompletionCondition>(completion_condition),
247
        device_(device),
248
        offset_(offset),
249
        buffer_(buffers),
250
        start_(0),
251
        total_transferred_(0),
252
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
253
    {
254
    }
255

    
256
#if defined(BOOST_ASIO_HAS_MOVE)
257
    read_at_op(const read_at_op& other)
258
      : detail::base_from_completion_cond<CompletionCondition>(other),
259
        device_(other.device_),
260
        offset_(other.offset_),
261
        buffer_(other.buffer_),
262
        start_(other.start_),
263
        total_transferred_(other.total_transferred_),
264
        handler_(other.handler_)
265
    {
266
    }
267

    
268
    read_at_op(read_at_op&& other)
269
      : detail::base_from_completion_cond<CompletionCondition>(other),
270
        device_(other.device_),
271
        offset_(other.offset_),
272
        buffer_(other.buffer_),
273
        start_(other.start_),
274
        total_transferred_(other.total_transferred_),
275
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
276
    {
277
    }
278
#endif // defined(BOOST_ASIO_HAS_MOVE)
279

    
280
    void operator()(const boost::system::error_code& ec,
281
        std::size_t bytes_transferred, int start = 0)
282
    {
283
      std::size_t n = 0;
284
      switch (start_ = start)
285
      {
286
        case 1:
287
        n = this->check_for_completion(ec, total_transferred_);
288
        for (;;)
289
        {
290
          device_.async_read_some_at(offset_ + total_transferred_,
291
              boost::asio::buffer(buffer_ + total_transferred_, n),
292
              BOOST_ASIO_MOVE_CAST(read_at_op)(*this));
293
          return; default:
294
          total_transferred_ += bytes_transferred;
295
          if ((!ec && bytes_transferred == 0)
296
              || (n = this->check_for_completion(ec, total_transferred_)) == 0
297
              || total_transferred_ == boost::asio::buffer_size(buffer_))
298
            break;
299
        }
300

    
301
        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
302
      }
303
    }
304

    
305
  //private:
306
    AsyncRandomAccessReadDevice& device_;
307
    uint64_t offset_;
308
    boost::asio::mutable_buffer buffer_;
309
    int start_;
310
    std::size_t total_transferred_;
311
    ReadHandler handler_;
312
  };
313

    
314
  template <typename AsyncRandomAccessReadDevice, typename Elem,
315
      typename CompletionCondition, typename ReadHandler>
316
  class read_at_op<AsyncRandomAccessReadDevice, boost::array<Elem, 2>,
317
      CompletionCondition, ReadHandler>
318
    : detail::base_from_completion_cond<CompletionCondition>
319
  {
320
  public:
321
    read_at_op(AsyncRandomAccessReadDevice& device,
322
        uint64_t offset, const boost::array<Elem, 2>& buffers,
323
        CompletionCondition completion_condition, ReadHandler& handler)
324
      : detail::base_from_completion_cond<
325
          CompletionCondition>(completion_condition),
326
        device_(device),
327
        offset_(offset),
328
        buffers_(buffers),
329
        start_(0),
330
        total_transferred_(0),
331
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
332
    {
333
    }
334

    
335
#if defined(BOOST_ASIO_HAS_MOVE)
336
    read_at_op(const read_at_op& other)
337
      : detail::base_from_completion_cond<CompletionCondition>(other),
338
        device_(other.device_),
339
        offset_(other.offset_),
340
        buffers_(other.buffers_),
341
        start_(other.start_),
342
        total_transferred_(other.total_transferred_),
343
        handler_(other.handler_)
344
    {
345
    }
346

    
347
    read_at_op(read_at_op&& other)
348
      : detail::base_from_completion_cond<CompletionCondition>(other),
349
        device_(other.device_),
350
        offset_(other.offset_),
351
        buffers_(other.buffers_),
352
        start_(other.start_),
353
        total_transferred_(other.total_transferred_),
354
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
355
    {
356
    }
357
#endif // defined(BOOST_ASIO_HAS_MOVE)
358

    
359
    void operator()(const boost::system::error_code& ec,
360
        std::size_t bytes_transferred, int start = 0)
361
    {
362
      typename boost::asio::detail::dependent_type<Elem,
363
          boost::array<boost::asio::mutable_buffer, 2> >::type bufs = {{
364
        boost::asio::mutable_buffer(buffers_[0]),
365
        boost::asio::mutable_buffer(buffers_[1]) }};
366
      std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
367
      std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
368
      std::size_t n = 0;
369
      switch (start_ = start)
370
      {
371
        case 1:
372
        n = this->check_for_completion(ec, total_transferred_);
373
        for (;;)
374
        {
375
          bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n);
376
          bufs[1] = boost::asio::buffer(
377
              bufs[1] + (total_transferred_ < buffer_size0
378
                ? 0 : total_transferred_ - buffer_size0),
379
              n - boost::asio::buffer_size(bufs[0]));
380
          device_.async_read_some_at(offset_ + total_transferred_,
381
              bufs, BOOST_ASIO_MOVE_CAST(read_at_op)(*this));
382
          return; default:
383
          total_transferred_ += bytes_transferred;
384
          if ((!ec && bytes_transferred == 0)
385
              || (n = this->check_for_completion(ec, total_transferred_)) == 0
386
              || total_transferred_ == buffer_size0 + buffer_size1)
387
            break;
388
        }
389

    
390
        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
391
      }
392
    }
393

    
394
  //private:
395
    AsyncRandomAccessReadDevice& device_;
396
    uint64_t offset_;
397
    boost::array<Elem, 2> buffers_;
398
    int start_;
399
    std::size_t total_transferred_;
400
    ReadHandler handler_;
401
  };
402

    
403
#if defined(BOOST_ASIO_HAS_STD_ARRAY)
404

    
405
  template <typename AsyncRandomAccessReadDevice, typename Elem,
406
      typename CompletionCondition, typename ReadHandler>
407
  class read_at_op<AsyncRandomAccessReadDevice, std::array<Elem, 2>,
408
      CompletionCondition, ReadHandler>
409
    : detail::base_from_completion_cond<CompletionCondition>
410
  {
411
  public:
412
    read_at_op(AsyncRandomAccessReadDevice& device,
413
        uint64_t offset, const std::array<Elem, 2>& buffers,
414
        CompletionCondition completion_condition, ReadHandler& handler)
415
      : detail::base_from_completion_cond<
416
          CompletionCondition>(completion_condition),
417
        device_(device),
418
        offset_(offset),
419
        buffers_(buffers),
420
        start_(0),
421
        total_transferred_(0),
422
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
423
    {
424
    }
425

    
426
#if defined(BOOST_ASIO_HAS_MOVE)
427
    read_at_op(const read_at_op& other)
428
      : detail::base_from_completion_cond<CompletionCondition>(other),
429
        device_(other.device_),
430
        offset_(other.offset_),
431
        buffers_(other.buffers_),
432
        start_(other.start_),
433
        total_transferred_(other.total_transferred_),
434
        handler_(other.handler_)
435
    {
436
    }
437

    
438
    read_at_op(read_at_op&& other)
439
      : detail::base_from_completion_cond<CompletionCondition>(other),
440
        device_(other.device_),
441
        offset_(other.offset_),
442
        buffers_(other.buffers_),
443
        start_(other.start_),
444
        total_transferred_(other.total_transferred_),
445
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
446
    {
447
    }
448
#endif // defined(BOOST_ASIO_HAS_MOVE)
449

    
450
    void operator()(const boost::system::error_code& ec,
451
        std::size_t bytes_transferred, int start = 0)
452
    {
453
      typename boost::asio::detail::dependent_type<Elem,
454
          std::array<boost::asio::mutable_buffer, 2> >::type bufs = {{
455
        boost::asio::mutable_buffer(buffers_[0]),
456
        boost::asio::mutable_buffer(buffers_[1]) }};
457
      std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
458
      std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
459
      std::size_t n = 0;
460
      switch (start_ = start)
461
      {
462
        case 1:
463
        n = this->check_for_completion(ec, total_transferred_);
464
        for (;;)
465
        {
466
          bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n);
467
          bufs[1] = boost::asio::buffer(
468
              bufs[1] + (total_transferred_ < buffer_size0
469
                ? 0 : total_transferred_ - buffer_size0),
470
              n - boost::asio::buffer_size(bufs[0]));
471
          device_.async_read_some_at(offset_ + total_transferred_,
472
              bufs, BOOST_ASIO_MOVE_CAST(read_at_op)(*this));
473
          return; default:
474
          total_transferred_ += bytes_transferred;
475
          if ((!ec && bytes_transferred == 0)
476
              || (n = this->check_for_completion(ec, total_transferred_)) == 0
477
              || total_transferred_ == buffer_size0 + buffer_size1)
478
            break;
479
        }
480

    
481
        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
482
      }
483
    }
484

    
485
  //private:
486
    AsyncRandomAccessReadDevice& device_;
487
    uint64_t offset_;
488
    std::array<Elem, 2> buffers_;
489
    int start_;
490
    std::size_t total_transferred_;
491
    ReadHandler handler_;
492
  };
493

    
494
#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
495

    
496
  template <typename AsyncRandomAccessReadDevice,
497
      typename MutableBufferSequence, typename CompletionCondition,
498
      typename ReadHandler>
499
  inline void* asio_handler_allocate(std::size_t size,
500
      read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
501
        CompletionCondition, ReadHandler>* this_handler)
502
  {
503
    return boost_asio_handler_alloc_helpers::allocate(
504
        size, this_handler->handler_);
505
  }
506

    
507
  template <typename AsyncRandomAccessReadDevice,
508
      typename MutableBufferSequence, typename CompletionCondition,
509
      typename ReadHandler>
510
  inline void asio_handler_deallocate(void* pointer, std::size_t size,
511
      read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
512
        CompletionCondition, ReadHandler>* this_handler)
513
  {
514
    boost_asio_handler_alloc_helpers::deallocate(
515
        pointer, size, this_handler->handler_);
516
  }
517

    
518
  template <typename AsyncRandomAccessReadDevice,
519
      typename MutableBufferSequence, typename CompletionCondition,
520
      typename ReadHandler>
521
  inline bool asio_handler_is_continuation(
522
      read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
523
        CompletionCondition, ReadHandler>* this_handler)
524
  {
525
    return this_handler->start_ == 0 ? true
526
      : boost_asio_handler_cont_helpers::is_continuation(
527
          this_handler->handler_);
528
  }
529

    
530
  template <typename Function, typename AsyncRandomAccessReadDevice,
531
      typename MutableBufferSequence, typename CompletionCondition,
532
      typename ReadHandler>
533
  inline void asio_handler_invoke(Function& function,
534
      read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
535
        CompletionCondition, ReadHandler>* this_handler)
536
  {
537
    boost_asio_handler_invoke_helpers::invoke(
538
        function, this_handler->handler_);
539
  }
540

    
541
  template <typename Function, typename AsyncRandomAccessReadDevice,
542
      typename MutableBufferSequence, typename CompletionCondition,
543
      typename ReadHandler>
544
  inline void asio_handler_invoke(const Function& function,
545
      read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
546
        CompletionCondition, ReadHandler>* this_handler)
547
  {
548
    boost_asio_handler_invoke_helpers::invoke(
549
        function, this_handler->handler_);
550
  }
551

    
552
  template <typename AsyncRandomAccessReadDevice,
553
      typename MutableBufferSequence, typename CompletionCondition,
554
      typename ReadHandler>
555
  inline read_at_op<AsyncRandomAccessReadDevice,
556
      MutableBufferSequence, CompletionCondition, ReadHandler>
557
  make_read_at_op(AsyncRandomAccessReadDevice& d,
558
      uint64_t offset, const MutableBufferSequence& buffers,
559
      CompletionCondition completion_condition, ReadHandler handler)
560
  {
561
    return read_at_op<AsyncRandomAccessReadDevice,
562
      MutableBufferSequence, CompletionCondition, ReadHandler>(
563
        d, offset, buffers, completion_condition, handler);
564
  }
565
} // namespace detail
566

    
567
template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
568
    typename CompletionCondition, typename ReadHandler>
569
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
570
    void (boost::system::error_code, std::size_t))
571
async_read_at(AsyncRandomAccessReadDevice& d,
572
    uint64_t offset, const MutableBufferSequence& buffers,
573
    CompletionCondition completion_condition,
574
    BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
575
{
576
  // If you get an error on the following line it means that your handler does
577
  // not meet the documented type requirements for a ReadHandler.
578
  BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
579

    
580
  detail::async_result_init<
581
    ReadHandler, void (boost::system::error_code, std::size_t)> init(
582
      BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
583

    
584
  detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
585
    CompletionCondition, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
586
      void (boost::system::error_code, std::size_t))>(
587
        d, offset, buffers, completion_condition, init.handler)(
588
          boost::system::error_code(), 0, 1);
589

    
590
  return init.result.get();
591
}
592

    
593
template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
594
    typename ReadHandler>
595
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
596
    void (boost::system::error_code, std::size_t))
597
async_read_at(AsyncRandomAccessReadDevice& d,
598
    uint64_t offset, const MutableBufferSequence& buffers,
599
    BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
600
{
601
  // If you get an error on the following line it means that your handler does
602
  // not meet the documented type requirements for a ReadHandler.
603
  BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
604

    
605
  detail::async_result_init<
606
    ReadHandler, void (boost::system::error_code, std::size_t)> init(
607
      BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
608

    
609
  detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
610
    detail::transfer_all_t, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
611
      void (boost::system::error_code, std::size_t))>(
612
        d, offset, buffers, transfer_all(), init.handler)(
613
          boost::system::error_code(), 0, 1);
614

    
615
  return init.result.get();
616
}
617

    
618
#if !defined(BOOST_ASIO_NO_IOSTREAM)
619

    
620
namespace detail
621
{
622
  template <typename AsyncRandomAccessReadDevice, typename Allocator,
623
      typename CompletionCondition, typename ReadHandler>
624
  class read_at_streambuf_op
625
    : detail::base_from_completion_cond<CompletionCondition>
626
  {
627
  public:
628
    read_at_streambuf_op(AsyncRandomAccessReadDevice& device,
629
        uint64_t offset, basic_streambuf<Allocator>& streambuf,
630
        CompletionCondition completion_condition, ReadHandler& handler)
631
      : detail::base_from_completion_cond<
632
          CompletionCondition>(completion_condition),
633
        device_(device),
634
        offset_(offset),
635
        streambuf_(streambuf),
636
        start_(0),
637
        total_transferred_(0),
638
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
639
    {
640
    }
641

    
642
#if defined(BOOST_ASIO_HAS_MOVE)
643
    read_at_streambuf_op(const read_at_streambuf_op& other)
644
      : detail::base_from_completion_cond<CompletionCondition>(other),
645
        device_(other.device_),
646
        offset_(other.offset_),
647
        streambuf_(other.streambuf_),
648
        start_(other.start_),
649
        total_transferred_(other.total_transferred_),
650
        handler_(other.handler_)
651
    {
652
    }
653

    
654
    read_at_streambuf_op(read_at_streambuf_op&& other)
655
      : detail::base_from_completion_cond<CompletionCondition>(other),
656
        device_(other.device_),
657
        offset_(other.offset_),
658
        streambuf_(other.streambuf_),
659
        start_(other.start_),
660
        total_transferred_(other.total_transferred_),
661
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
662
    {
663
    }
664
#endif // defined(BOOST_ASIO_HAS_MOVE)
665

    
666
    void operator()(const boost::system::error_code& ec,
667
        std::size_t bytes_transferred, int start = 0)
668
    {
669
      std::size_t max_size, bytes_available;
670
      switch (start_ = start)
671
      {
672
        case 1:
673
        max_size = this->check_for_completion(ec, total_transferred_);
674
        bytes_available = read_size_helper(streambuf_, max_size);
675
        for (;;)
676
        {
677
          device_.async_read_some_at(offset_ + total_transferred_,
678
              streambuf_.prepare(bytes_available),
679
              BOOST_ASIO_MOVE_CAST(read_at_streambuf_op)(*this));
680
          return; default:
681
          total_transferred_ += bytes_transferred;
682
          streambuf_.commit(bytes_transferred);
683
          max_size = this->check_for_completion(ec, total_transferred_);
684
          bytes_available = read_size_helper(streambuf_, max_size);
685
          if ((!ec && bytes_transferred == 0) || bytes_available == 0)
686
            break;
687
        }
688

    
689
        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
690
      }
691
    }
692

    
693
  //private:
694
    AsyncRandomAccessReadDevice& device_;
695
    uint64_t offset_;
696
    boost::asio::basic_streambuf<Allocator>& streambuf_;
697
    int start_;
698
    std::size_t total_transferred_;
699
    ReadHandler handler_;
700
  };
701

    
702
  template <typename AsyncRandomAccessReadDevice, typename Allocator,
703
      typename CompletionCondition, typename ReadHandler>
704
  inline void* asio_handler_allocate(std::size_t size,
705
      read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
706
        CompletionCondition, ReadHandler>* this_handler)
707
  {
708
    return boost_asio_handler_alloc_helpers::allocate(
709
        size, this_handler->handler_);
710
  }
711

    
712
  template <typename AsyncRandomAccessReadDevice, typename Allocator,
713
      typename CompletionCondition, typename ReadHandler>
714
  inline void asio_handler_deallocate(void* pointer, std::size_t size,
715
      read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
716
        CompletionCondition, ReadHandler>* this_handler)
717
  {
718
    boost_asio_handler_alloc_helpers::deallocate(
719
        pointer, size, this_handler->handler_);
720
  }
721

    
722
  template <typename AsyncRandomAccessReadDevice, typename Allocator,
723
      typename CompletionCondition, typename ReadHandler>
724
  inline bool asio_handler_is_continuation(
725
      read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
726
        CompletionCondition, ReadHandler>* this_handler)
727
  {
728
    return this_handler->start_ == 0 ? true
729
      : boost_asio_handler_cont_helpers::is_continuation(
730
          this_handler->handler_);
731
  }
732

    
733
  template <typename Function, typename AsyncRandomAccessReadDevice,
734
      typename Allocator, typename CompletionCondition, typename ReadHandler>
735
  inline void asio_handler_invoke(Function& function,
736
      read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
737
        CompletionCondition, ReadHandler>* this_handler)
738
  {
739
    boost_asio_handler_invoke_helpers::invoke(
740
        function, this_handler->handler_);
741
  }
742

    
743
  template <typename Function, typename AsyncRandomAccessReadDevice,
744
      typename Allocator, typename CompletionCondition, typename ReadHandler>
745
  inline void asio_handler_invoke(const Function& function,
746
      read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
747
        CompletionCondition, ReadHandler>* this_handler)
748
  {
749
    boost_asio_handler_invoke_helpers::invoke(
750
        function, this_handler->handler_);
751
  }
752
} // namespace detail
753

    
754
template <typename AsyncRandomAccessReadDevice, typename Allocator,
755
    typename CompletionCondition, typename ReadHandler>
756
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
757
    void (boost::system::error_code, std::size_t))
758
async_read_at(AsyncRandomAccessReadDevice& d,
759
    uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
760
    CompletionCondition completion_condition,
761
    BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
762
{
763
  // If you get an error on the following line it means that your handler does
764
  // not meet the documented type requirements for a ReadHandler.
765
  BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
766

    
767
  detail::async_result_init<
768
    ReadHandler, void (boost::system::error_code, std::size_t)> init(
769
      BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
770

    
771
  detail::read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
772
    CompletionCondition, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
773
      void (boost::system::error_code, std::size_t))>(
774
        d, offset, b, completion_condition, init.handler)(
775
          boost::system::error_code(), 0, 1);
776

    
777
  return init.result.get();
778
}
779

    
780
template <typename AsyncRandomAccessReadDevice, typename Allocator,
781
    typename ReadHandler>
782
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
783
    void (boost::system::error_code, std::size_t))
784
async_read_at(AsyncRandomAccessReadDevice& d,
785
    uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
786
    BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
787
{
788
  // If you get an error on the following line it means that your handler does
789
  // not meet the documented type requirements for a ReadHandler.
790
  BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
791

    
792
  detail::async_result_init<
793
    ReadHandler, void (boost::system::error_code, std::size_t)> init(
794
      BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
795

    
796
  detail::read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
797
    detail::transfer_all_t, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
798
      void (boost::system::error_code, std::size_t))>(
799
        d, offset, b, transfer_all(), init.handler)(
800
          boost::system::error_code(), 0, 1);
801

    
802
  return init.result.get();
803
}
804

    
805
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
806

    
807
} // namespace asio
808
} // namespace boost
809

    
810
#include <boost/asio/detail/pop_options.hpp>
811

    
812
#endif // BOOST_ASIO_IMPL_READ_AT_HPP