Statistics
| Revision:

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

History | View | Annotate | Download (26.2 kB)

1
//
2
// impl/read.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_HPP
12
#define BOOST_ASIO_IMPL_READ_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 SyncReadStream, typename MutableBufferSequence,
39
    typename CompletionCondition>
40
std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
41
    CompletionCondition completion_condition, boost::system::error_code& ec)
42
{
43
  ec = boost::system::error_code();
44
  boost::asio::detail::consuming_buffers<
45
    mutable_buffer, MutableBufferSequence> tmp(buffers);
46
  std::size_t total_transferred = 0;
47
  tmp.prepare(detail::adapt_completion_condition_result(
48
        completion_condition(ec, total_transferred)));
49
  while (tmp.begin() != tmp.end())
50
  {
51
    std::size_t bytes_transferred = s.read_some(tmp, ec);
52
    tmp.consume(bytes_transferred);
53
    total_transferred += bytes_transferred;
54
    tmp.prepare(detail::adapt_completion_condition_result(
55
          completion_condition(ec, total_transferred)));
56
  }
57
  return total_transferred;
58
}
59

    
60
template <typename SyncReadStream, typename MutableBufferSequence>
61
inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers)
62
{
63
  boost::system::error_code ec;
64
  std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
65
  boost::asio::detail::throw_error(ec, "read");
66
  return bytes_transferred;
67
}
68

    
69
template <typename SyncReadStream, typename MutableBufferSequence>
70
inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
71
    boost::system::error_code& ec)
72
{
73
  return read(s, buffers, transfer_all(), ec);
74
}
75

    
76
template <typename SyncReadStream, typename MutableBufferSequence,
77
    typename CompletionCondition>
78
inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
79
    CompletionCondition completion_condition)
80
{
81
  boost::system::error_code ec;
82
  std::size_t bytes_transferred = read(s, buffers, completion_condition, ec);
83
  boost::asio::detail::throw_error(ec, "read");
84
  return bytes_transferred;
85
}
86

    
87
#if !defined(BOOST_ASIO_NO_IOSTREAM)
88

    
89
template <typename SyncReadStream, typename Allocator,
90
    typename CompletionCondition>
91
std::size_t read(SyncReadStream& s,
92
    boost::asio::basic_streambuf<Allocator>& b,
93
    CompletionCondition completion_condition, boost::system::error_code& ec)
94
{
95
  ec = boost::system::error_code();
96
  std::size_t total_transferred = 0;
97
  std::size_t max_size = detail::adapt_completion_condition_result(
98
        completion_condition(ec, total_transferred));
99
  std::size_t bytes_available = read_size_helper(b, max_size);
100
  while (bytes_available > 0)
101
  {
102
    std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
103
    b.commit(bytes_transferred);
104
    total_transferred += bytes_transferred;
105
    max_size = detail::adapt_completion_condition_result(
106
          completion_condition(ec, total_transferred));
107
    bytes_available = read_size_helper(b, max_size);
108
  }
109
  return total_transferred;
110
}
111

    
112
template <typename SyncReadStream, typename Allocator>
113
inline std::size_t read(SyncReadStream& s,
114
    boost::asio::basic_streambuf<Allocator>& b)
115
{
116
  boost::system::error_code ec;
117
  std::size_t bytes_transferred = read(s, b, transfer_all(), ec);
118
  boost::asio::detail::throw_error(ec, "read");
119
  return bytes_transferred;
120
}
121

    
122
template <typename SyncReadStream, typename Allocator>
123
inline std::size_t read(SyncReadStream& s,
124
    boost::asio::basic_streambuf<Allocator>& b,
125
    boost::system::error_code& ec)
126
{
127
  return read(s, b, transfer_all(), ec);
128
}
129

    
130
template <typename SyncReadStream, typename Allocator,
131
    typename CompletionCondition>
132
inline std::size_t read(SyncReadStream& s,
133
    boost::asio::basic_streambuf<Allocator>& b,
134
    CompletionCondition completion_condition)
135
{
136
  boost::system::error_code ec;
137
  std::size_t bytes_transferred = read(s, b, completion_condition, ec);
138
  boost::asio::detail::throw_error(ec, "read");
139
  return bytes_transferred;
140
}
141

    
142
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
143

    
144
namespace detail
145
{
146
  template <typename AsyncReadStream, typename MutableBufferSequence,
147
      typename CompletionCondition, typename ReadHandler>
148
  class read_op
149
    : detail::base_from_completion_cond<CompletionCondition>
150
  {
151
  public:
152
    read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers,
153
        CompletionCondition completion_condition, ReadHandler& handler)
154
      : detail::base_from_completion_cond<
155
          CompletionCondition>(completion_condition),
156
        stream_(stream),
157
        buffers_(buffers),
158
        start_(0),
159
        total_transferred_(0),
160
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
161
    {
162
    }
163

    
164
#if defined(BOOST_ASIO_HAS_MOVE)
165
    read_op(const read_op& other)
166
      : detail::base_from_completion_cond<CompletionCondition>(other),
167
        stream_(other.stream_),
168
        buffers_(other.buffers_),
169
        start_(other.start_),
170
        total_transferred_(other.total_transferred_),
171
        handler_(other.handler_)
172
    {
173
    }
174

    
175
    read_op(read_op&& other)
176
      : detail::base_from_completion_cond<CompletionCondition>(other),
177
        stream_(other.stream_),
178
        buffers_(other.buffers_),
179
        start_(other.start_),
180
        total_transferred_(other.total_transferred_),
181
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
182
    {
183
    }
184
#endif // defined(BOOST_ASIO_HAS_MOVE)
185

    
186
    void operator()(const boost::system::error_code& ec,
187
        std::size_t bytes_transferred, int start = 0)
188
    {
189
      switch (start_ = start)
190
      {
191
        case 1:
192
        buffers_.prepare(this->check_for_completion(ec, total_transferred_));
193
        for (;;)
194
        {
195
          stream_.async_read_some(buffers_,
196
              BOOST_ASIO_MOVE_CAST(read_op)(*this));
197
          return; default:
198
          total_transferred_ += bytes_transferred;
199
          buffers_.consume(bytes_transferred);
200
          buffers_.prepare(this->check_for_completion(ec, total_transferred_));
201
          if ((!ec && bytes_transferred == 0)
202
              || buffers_.begin() == buffers_.end())
203
            break;
204
        }
205

    
206
        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
207
      }
208
    }
209

    
210
  //private:
211
    AsyncReadStream& stream_;
212
    boost::asio::detail::consuming_buffers<
213
      mutable_buffer, MutableBufferSequence> buffers_;
214
    int start_;
215
    std::size_t total_transferred_;
216
    ReadHandler handler_;
217
  };
218

    
219
  template <typename AsyncReadStream,
220
      typename CompletionCondition, typename ReadHandler>
221
  class read_op<AsyncReadStream, boost::asio::mutable_buffers_1,
222
      CompletionCondition, ReadHandler>
223
    : detail::base_from_completion_cond<CompletionCondition>
224
  {
225
  public:
226
    read_op(AsyncReadStream& stream,
227
        const boost::asio::mutable_buffers_1& buffers,
228
        CompletionCondition completion_condition, ReadHandler& handler)
229
      : detail::base_from_completion_cond<
230
          CompletionCondition>(completion_condition),
231
        stream_(stream),
232
        buffer_(buffers),
233
        start_(0),
234
        total_transferred_(0),
235
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
236
    {
237
    }
238

    
239
#if defined(BOOST_ASIO_HAS_MOVE)
240
    read_op(const read_op& other)
241
      : detail::base_from_completion_cond<CompletionCondition>(other),
242
        stream_(other.stream_),
243
        buffer_(other.buffer_),
244
        start_(other.start_),
245
        total_transferred_(other.total_transferred_),
246
        handler_(other.handler_)
247
    {
248
    }
249

    
250
    read_op(read_op&& other)
251
      : detail::base_from_completion_cond<CompletionCondition>(other),
252
        stream_(other.stream_),
253
        buffer_(other.buffer_),
254
        start_(other.start_),
255
        total_transferred_(other.total_transferred_),
256
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
257
    {
258
    }
259
#endif // defined(BOOST_ASIO_HAS_MOVE)
260

    
261
    void operator()(const boost::system::error_code& ec,
262
        std::size_t bytes_transferred, int start = 0)
263
    {
264
      std::size_t n = 0;
265
      switch (start_ = start)
266
      {
267
        case 1:
268
        n = this->check_for_completion(ec, total_transferred_);
269
        for (;;)
270
        {
271
          stream_.async_read_some(
272
              boost::asio::buffer(buffer_ + total_transferred_, n),
273
              BOOST_ASIO_MOVE_CAST(read_op)(*this));
274
          return; default:
275
          total_transferred_ += bytes_transferred;
276
          if ((!ec && bytes_transferred == 0)
277
              || (n = this->check_for_completion(ec, total_transferred_)) == 0
278
              || total_transferred_ == boost::asio::buffer_size(buffer_))
279
            break;
280
        }
281

    
282
        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
283
      }
284
    }
285

    
286
  //private:
287
    AsyncReadStream& stream_;
288
    boost::asio::mutable_buffer buffer_;
289
    int start_;
290
    std::size_t total_transferred_;
291
    ReadHandler handler_;
292
  };
293

    
294
  template <typename AsyncReadStream, typename Elem,
295
      typename CompletionCondition, typename ReadHandler>
296
  class read_op<AsyncReadStream, boost::array<Elem, 2>,
297
      CompletionCondition, ReadHandler>
298
    : detail::base_from_completion_cond<CompletionCondition>
299
  {
300
  public:
301
    read_op(AsyncReadStream& stream, const boost::array<Elem, 2>& buffers,
302
        CompletionCondition completion_condition, ReadHandler& handler)
303
      : detail::base_from_completion_cond<
304
          CompletionCondition>(completion_condition),
305
        stream_(stream),
306
        buffers_(buffers),
307
        start_(0),
308
        total_transferred_(0),
309
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
310
    {
311
    }
312

    
313
#if defined(BOOST_ASIO_HAS_MOVE)
314
    read_op(const read_op& other)
315
      : detail::base_from_completion_cond<CompletionCondition>(other),
316
        stream_(other.stream_),
317
        buffers_(other.buffers_),
318
        start_(other.start_),
319
        total_transferred_(other.total_transferred_),
320
        handler_(other.handler_)
321
    {
322
    }
323

    
324
    read_op(read_op&& other)
325
      : detail::base_from_completion_cond<CompletionCondition>(other),
326
        stream_(other.stream_),
327
        buffers_(other.buffers_),
328
        start_(other.start_),
329
        total_transferred_(other.total_transferred_),
330
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
331
    {
332
    }
333
#endif // defined(BOOST_ASIO_HAS_MOVE)
334

    
335
    void operator()(const boost::system::error_code& ec,
336
        std::size_t bytes_transferred, int start = 0)
337
    {
338
      typename boost::asio::detail::dependent_type<Elem,
339
          boost::array<boost::asio::mutable_buffer, 2> >::type bufs = {{
340
        boost::asio::mutable_buffer(buffers_[0]),
341
        boost::asio::mutable_buffer(buffers_[1]) }};
342
      std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
343
      std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
344
      std::size_t n = 0;
345
      switch (start_ = start)
346
      {
347
        case 1:
348
        n = this->check_for_completion(ec, total_transferred_);
349
        for (;;)
350
        {
351
          bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n);
352
          bufs[1] = boost::asio::buffer(
353
              bufs[1] + (total_transferred_ < buffer_size0
354
                ? 0 : total_transferred_ - buffer_size0),
355
              n - boost::asio::buffer_size(bufs[0]));
356
          stream_.async_read_some(bufs, BOOST_ASIO_MOVE_CAST(read_op)(*this));
357
          return; default:
358
          total_transferred_ += bytes_transferred;
359
          if ((!ec && bytes_transferred == 0)
360
              || (n = this->check_for_completion(ec, total_transferred_)) == 0
361
              || total_transferred_ == buffer_size0 + buffer_size1)
362
            break;
363
        }
364

    
365
        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
366
      }
367
    }
368

    
369
  //private:
370
    AsyncReadStream& stream_;
371
    boost::array<Elem, 2> buffers_;
372
    int start_;
373
    std::size_t total_transferred_;
374
    ReadHandler handler_;
375
  };
376

    
377
#if defined(BOOST_ASIO_HAS_STD_ARRAY)
378

    
379
  template <typename AsyncReadStream, typename Elem,
380
      typename CompletionCondition, typename ReadHandler>
381
  class read_op<AsyncReadStream, std::array<Elem, 2>,
382
      CompletionCondition, ReadHandler>
383
    : detail::base_from_completion_cond<CompletionCondition>
384
  {
385
  public:
386
    read_op(AsyncReadStream& stream, const std::array<Elem, 2>& buffers,
387
        CompletionCondition completion_condition, ReadHandler& handler)
388
      : detail::base_from_completion_cond<
389
          CompletionCondition>(completion_condition),
390
        stream_(stream),
391
        buffers_(buffers),
392
        start_(0),
393
        total_transferred_(0),
394
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
395
    {
396
    }
397

    
398
#if defined(BOOST_ASIO_HAS_MOVE)
399
    read_op(const read_op& other)
400
      : detail::base_from_completion_cond<CompletionCondition>(other),
401
        stream_(other.stream_),
402
        buffers_(other.buffers_),
403
        start_(other.start_),
404
        total_transferred_(other.total_transferred_),
405
        handler_(other.handler_)
406
    {
407
    }
408

    
409
    read_op(read_op&& other)
410
      : detail::base_from_completion_cond<CompletionCondition>(other),
411
        stream_(other.stream_),
412
        buffers_(other.buffers_),
413
        start_(other.start_),
414
        total_transferred_(other.total_transferred_),
415
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
416
    {
417
    }
418
#endif // defined(BOOST_ASIO_HAS_MOVE)
419

    
420
    void operator()(const boost::system::error_code& ec,
421
        std::size_t bytes_transferred, int start = 0)
422
    {
423
      typename boost::asio::detail::dependent_type<Elem,
424
          std::array<boost::asio::mutable_buffer, 2> >::type bufs = {{
425
        boost::asio::mutable_buffer(buffers_[0]),
426
        boost::asio::mutable_buffer(buffers_[1]) }};
427
      std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
428
      std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
429
      std::size_t n = 0;
430
      switch (start_ = start)
431
      {
432
        case 1:
433
        n = this->check_for_completion(ec, total_transferred_);
434
        for (;;)
435
        {
436
          bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n);
437
          bufs[1] = boost::asio::buffer(
438
              bufs[1] + (total_transferred_ < buffer_size0
439
                ? 0 : total_transferred_ - buffer_size0),
440
              n - boost::asio::buffer_size(bufs[0]));
441
          stream_.async_read_some(bufs, BOOST_ASIO_MOVE_CAST(read_op)(*this));
442
          return; default:
443
          total_transferred_ += bytes_transferred;
444
          if ((!ec && bytes_transferred == 0)
445
              || (n = this->check_for_completion(ec, total_transferred_)) == 0
446
              || total_transferred_ == buffer_size0 + buffer_size1)
447
            break;
448
        }
449

    
450
        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
451
      }
452
    }
453

    
454
  //private:
455
    AsyncReadStream& stream_;
456
    std::array<Elem, 2> buffers_;
457
    int start_;
458
    std::size_t total_transferred_;
459
    ReadHandler handler_;
460
  };
461

    
462
#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
463

    
464
  template <typename AsyncReadStream, typename MutableBufferSequence,
465
      typename CompletionCondition, typename ReadHandler>
466
  inline void* asio_handler_allocate(std::size_t size,
467
      read_op<AsyncReadStream, MutableBufferSequence,
468
        CompletionCondition, ReadHandler>* this_handler)
469
  {
470
    return boost_asio_handler_alloc_helpers::allocate(
471
        size, this_handler->handler_);
472
  }
473

    
474
  template <typename AsyncReadStream, typename MutableBufferSequence,
475
      typename CompletionCondition, typename ReadHandler>
476
  inline void asio_handler_deallocate(void* pointer, std::size_t size,
477
      read_op<AsyncReadStream, MutableBufferSequence,
478
        CompletionCondition, ReadHandler>* this_handler)
479
  {
480
    boost_asio_handler_alloc_helpers::deallocate(
481
        pointer, size, this_handler->handler_);
482
  }
483

    
484
  template <typename AsyncReadStream, typename MutableBufferSequence,
485
      typename CompletionCondition, typename ReadHandler>
486
  inline bool asio_handler_is_continuation(
487
      read_op<AsyncReadStream, MutableBufferSequence,
488
        CompletionCondition, ReadHandler>* this_handler)
489
  {
490
    return this_handler->start_ == 0 ? true
491
      : boost_asio_handler_cont_helpers::is_continuation(
492
          this_handler->handler_);
493
  }
494

    
495
  template <typename Function, typename AsyncReadStream,
496
      typename MutableBufferSequence, typename CompletionCondition,
497
      typename ReadHandler>
498
  inline void asio_handler_invoke(Function& function,
499
      read_op<AsyncReadStream, MutableBufferSequence,
500
        CompletionCondition, ReadHandler>* this_handler)
501
  {
502
    boost_asio_handler_invoke_helpers::invoke(
503
        function, this_handler->handler_);
504
  }
505

    
506
  template <typename Function, typename AsyncReadStream,
507
      typename MutableBufferSequence, typename CompletionCondition,
508
      typename ReadHandler>
509
  inline void asio_handler_invoke(const Function& function,
510
      read_op<AsyncReadStream, MutableBufferSequence,
511
        CompletionCondition, ReadHandler>* this_handler)
512
  {
513
    boost_asio_handler_invoke_helpers::invoke(
514
        function, this_handler->handler_);
515
  }
516
} // namespace detail
517

    
518
template <typename AsyncReadStream, typename MutableBufferSequence,
519
    typename CompletionCondition, typename ReadHandler>
520
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
521
    void (boost::system::error_code, std::size_t))
522
async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
523
    CompletionCondition completion_condition,
524
    BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
525
{
526
  // If you get an error on the following line it means that your handler does
527
  // not meet the documented type requirements for a ReadHandler.
528
  BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
529

    
530
  detail::async_result_init<
531
    ReadHandler, void (boost::system::error_code, std::size_t)> init(
532
      BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
533

    
534
  detail::read_op<AsyncReadStream, MutableBufferSequence,
535
    CompletionCondition, BOOST_ASIO_HANDLER_TYPE(
536
      ReadHandler, void (boost::system::error_code, std::size_t))>(
537
        s, buffers, completion_condition, init.handler)(
538
          boost::system::error_code(), 0, 1);
539

    
540
  return init.result.get();
541
}
542

    
543
template <typename AsyncReadStream, typename MutableBufferSequence,
544
    typename ReadHandler>
545
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
546
    void (boost::system::error_code, std::size_t))
547
async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
548
    BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
549
{
550
  // If you get an error on the following line it means that your handler does
551
  // not meet the documented type requirements for a ReadHandler.
552
  BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
553

    
554
  detail::async_result_init<
555
    ReadHandler, void (boost::system::error_code, std::size_t)> init(
556
      BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
557

    
558
  detail::read_op<AsyncReadStream, MutableBufferSequence,
559
    detail::transfer_all_t, BOOST_ASIO_HANDLER_TYPE(
560
      ReadHandler, void (boost::system::error_code, std::size_t))>(
561
        s, buffers, transfer_all(), init.handler)(
562
          boost::system::error_code(), 0, 1);
563

    
564
  return init.result.get();
565
}
566

    
567
#if !defined(BOOST_ASIO_NO_IOSTREAM)
568

    
569
namespace detail
570
{
571
  template <typename AsyncReadStream, typename Allocator,
572
      typename CompletionCondition, typename ReadHandler>
573
  class read_streambuf_op
574
    : detail::base_from_completion_cond<CompletionCondition>
575
  {
576
  public:
577
    read_streambuf_op(AsyncReadStream& stream,
578
        basic_streambuf<Allocator>& streambuf,
579
        CompletionCondition completion_condition, ReadHandler& handler)
580
      : detail::base_from_completion_cond<
581
          CompletionCondition>(completion_condition),
582
        stream_(stream),
583
        streambuf_(streambuf),
584
        start_(0),
585
        total_transferred_(0),
586
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
587
    {
588
    }
589

    
590
#if defined(BOOST_ASIO_HAS_MOVE)
591
    read_streambuf_op(const read_streambuf_op& other)
592
      : detail::base_from_completion_cond<CompletionCondition>(other),
593
        stream_(other.stream_),
594
        streambuf_(other.streambuf_),
595
        start_(other.start_),
596
        total_transferred_(other.total_transferred_),
597
        handler_(other.handler_)
598
    {
599
    }
600

    
601
    read_streambuf_op(read_streambuf_op&& other)
602
      : detail::base_from_completion_cond<CompletionCondition>(other),
603
        stream_(other.stream_),
604
        streambuf_(other.streambuf_),
605
        start_(other.start_),
606
        total_transferred_(other.total_transferred_),
607
        handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
608
    {
609
    }
610
#endif // defined(BOOST_ASIO_HAS_MOVE)
611

    
612
    void operator()(const boost::system::error_code& ec,
613
        std::size_t bytes_transferred, int start = 0)
614
    {
615
      std::size_t max_size, bytes_available;
616
      switch (start_ = start)
617
      {
618
        case 1:
619
        max_size = this->check_for_completion(ec, total_transferred_);
620
        bytes_available = read_size_helper(streambuf_, max_size);
621
        for (;;)
622
        {
623
          stream_.async_read_some(streambuf_.prepare(bytes_available),
624
              BOOST_ASIO_MOVE_CAST(read_streambuf_op)(*this));
625
          return; default:
626
          total_transferred_ += bytes_transferred;
627
          streambuf_.commit(bytes_transferred);
628
          max_size = this->check_for_completion(ec, total_transferred_);
629
          bytes_available = read_size_helper(streambuf_, max_size);
630
          if ((!ec && bytes_transferred == 0) || bytes_available == 0)
631
            break;
632
        }
633

    
634
        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
635
      }
636
    }
637

    
638
  //private:
639
    AsyncReadStream& stream_;
640
    boost::asio::basic_streambuf<Allocator>& streambuf_;
641
    int start_;
642
    std::size_t total_transferred_;
643
    ReadHandler handler_;
644
  };
645

    
646
  template <typename AsyncReadStream, typename Allocator,
647
      typename CompletionCondition, typename ReadHandler>
648
  inline void* asio_handler_allocate(std::size_t size,
649
      read_streambuf_op<AsyncReadStream, Allocator,
650
        CompletionCondition, ReadHandler>* this_handler)
651
  {
652
    return boost_asio_handler_alloc_helpers::allocate(
653
        size, this_handler->handler_);
654
  }
655

    
656
  template <typename AsyncReadStream, typename Allocator,
657
      typename CompletionCondition, typename ReadHandler>
658
  inline void asio_handler_deallocate(void* pointer, std::size_t size,
659
      read_streambuf_op<AsyncReadStream, Allocator,
660
        CompletionCondition, ReadHandler>* this_handler)
661
  {
662
    boost_asio_handler_alloc_helpers::deallocate(
663
        pointer, size, this_handler->handler_);
664
  }
665

    
666
  template <typename AsyncReadStream, typename Allocator,
667
      typename CompletionCondition, typename ReadHandler>
668
  inline bool asio_handler_is_continuation(
669
      read_streambuf_op<AsyncReadStream, Allocator,
670
        CompletionCondition, ReadHandler>* this_handler)
671
  {
672
    return this_handler->start_ == 0 ? true
673
      : boost_asio_handler_cont_helpers::is_continuation(
674
          this_handler->handler_);
675
  }
676

    
677
  template <typename Function, typename AsyncReadStream,
678
      typename Allocator, typename CompletionCondition, typename ReadHandler>
679
  inline void asio_handler_invoke(Function& function,
680
      read_streambuf_op<AsyncReadStream, Allocator,
681
        CompletionCondition, ReadHandler>* this_handler)
682
  {
683
    boost_asio_handler_invoke_helpers::invoke(
684
        function, this_handler->handler_);
685
  }
686

    
687
  template <typename Function, typename AsyncReadStream,
688
      typename Allocator, typename CompletionCondition, typename ReadHandler>
689
  inline void asio_handler_invoke(const Function& function,
690
      read_streambuf_op<AsyncReadStream, Allocator,
691
        CompletionCondition, ReadHandler>* this_handler)
692
  {
693
    boost_asio_handler_invoke_helpers::invoke(
694
        function, this_handler->handler_);
695
  }
696
} // namespace detail
697

    
698
template <typename AsyncReadStream, typename Allocator,
699
    typename CompletionCondition, typename ReadHandler>
700
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
701
    void (boost::system::error_code, std::size_t))
702
async_read(AsyncReadStream& s,
703
    boost::asio::basic_streambuf<Allocator>& b,
704
    CompletionCondition completion_condition,
705
    BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
706
{
707
  // If you get an error on the following line it means that your handler does
708
  // not meet the documented type requirements for a ReadHandler.
709
  BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
710

    
711
  detail::async_result_init<
712
    ReadHandler, void (boost::system::error_code, std::size_t)> init(
713
      BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
714

    
715
  detail::read_streambuf_op<AsyncReadStream, Allocator,
716
    CompletionCondition, BOOST_ASIO_HANDLER_TYPE(
717
      ReadHandler, void (boost::system::error_code, std::size_t))>(
718
        s, b, completion_condition, init.handler)(
719
          boost::system::error_code(), 0, 1);
720

    
721
  return init.result.get();
722
}
723

    
724
template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
725
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
726
    void (boost::system::error_code, std::size_t))
727
async_read(AsyncReadStream& s,
728
    boost::asio::basic_streambuf<Allocator>& b,
729
    BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
730
{
731
  // If you get an error on the following line it means that your handler does
732
  // not meet the documented type requirements for a ReadHandler.
733
  BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
734

    
735
  detail::async_result_init<
736
    ReadHandler, void (boost::system::error_code, std::size_t)> init(
737
      BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
738

    
739
  detail::read_streambuf_op<AsyncReadStream, Allocator,
740
    detail::transfer_all_t, BOOST_ASIO_HANDLER_TYPE(
741
      ReadHandler, void (boost::system::error_code, std::size_t))>(
742
        s, b, transfer_all(), init.handler)(
743
          boost::system::error_code(), 0, 1);
744

    
745
  return init.result.get();
746
}
747

    
748
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
749

    
750
} // namespace asio
751
} // namespace boost
752

    
753
#include <boost/asio/detail/pop_options.hpp>
754

    
755
#endif // BOOST_ASIO_IMPL_READ_HPP