Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / asio / impl / buffered_read_stream.hpp
1 //
2 // impl/buffered_read_stream.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2019 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_BUFFERED_READ_STREAM_HPP
12 #define BOOST_ASIO_IMPL_BUFFERED_READ_STREAM_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/associated_allocator.hpp>
19 #include <boost/asio/associated_executor.hpp>
20 #include <boost/asio/detail/handler_alloc_helpers.hpp>
21 #include <boost/asio/detail/handler_cont_helpers.hpp>
22 #include <boost/asio/detail/handler_invoke_helpers.hpp>
23 #include <boost/asio/detail/handler_type_requirements.hpp>
24 #include <boost/asio/detail/non_const_lvalue.hpp>
25 #include <boost/asio/detail/type_traits.hpp>
26
27 #include <boost/asio/detail/push_options.hpp>
28
29 namespace boost {
30 namespace asio {
31
32 template <typename Stream>
33 std::size_t buffered_read_stream<Stream>::fill()
34 {
35   detail::buffer_resize_guard<detail::buffered_stream_storage>
36     resize_guard(storage_);
37   std::size_t previous_size = storage_.size();
38   storage_.resize(storage_.capacity());
39   storage_.resize(previous_size + next_layer_.read_some(buffer(
40           storage_.data() + previous_size,
41           storage_.size() - previous_size)));
42   resize_guard.commit();
43   return storage_.size() - previous_size;
44 }
45
46 template <typename Stream>
47 std::size_t buffered_read_stream<Stream>::fill(boost::system::error_code& ec)
48 {
49   detail::buffer_resize_guard<detail::buffered_stream_storage>
50     resize_guard(storage_);
51   std::size_t previous_size = storage_.size();
52   storage_.resize(storage_.capacity());
53   storage_.resize(previous_size + next_layer_.read_some(buffer(
54           storage_.data() + previous_size,
55           storage_.size() - previous_size),
56         ec));
57   resize_guard.commit();
58   return storage_.size() - previous_size;
59 }
60
61 namespace detail
62 {
63   template <typename ReadHandler>
64   class buffered_fill_handler
65   {
66   public:
67     buffered_fill_handler(detail::buffered_stream_storage& storage,
68         std::size_t previous_size, ReadHandler& handler)
69       : storage_(storage),
70         previous_size_(previous_size),
71         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
72     {
73     }
74
75 #if defined(BOOST_ASIO_HAS_MOVE)
76     buffered_fill_handler(const buffered_fill_handler& other)
77       : storage_(other.storage_),
78         previous_size_(other.previous_size_),
79         handler_(other.handler_)
80     {
81     }
82
83     buffered_fill_handler(buffered_fill_handler&& other)
84       : storage_(other.storage_),
85         previous_size_(other.previous_size_),
86         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
87     {
88     }
89 #endif // defined(BOOST_ASIO_HAS_MOVE)
90
91     void operator()(const boost::system::error_code& ec,
92         const std::size_t bytes_transferred)
93     {
94       storage_.resize(previous_size_ + bytes_transferred);
95       handler_(ec, bytes_transferred);
96     }
97
98   //private:
99     detail::buffered_stream_storage& storage_;
100     std::size_t previous_size_;
101     ReadHandler handler_;
102   };
103
104   template <typename ReadHandler>
105   inline void* asio_handler_allocate(std::size_t size,
106       buffered_fill_handler<ReadHandler>* this_handler)
107   {
108     return boost_asio_handler_alloc_helpers::allocate(
109         size, this_handler->handler_);
110   }
111
112   template <typename ReadHandler>
113   inline void asio_handler_deallocate(void* pointer, std::size_t size,
114       buffered_fill_handler<ReadHandler>* this_handler)
115   {
116     boost_asio_handler_alloc_helpers::deallocate(
117         pointer, size, this_handler->handler_);
118   }
119
120   template <typename ReadHandler>
121   inline bool asio_handler_is_continuation(
122       buffered_fill_handler<ReadHandler>* this_handler)
123   {
124     return boost_asio_handler_cont_helpers::is_continuation(
125           this_handler->handler_);
126   }
127
128   template <typename Function, typename ReadHandler>
129   inline void asio_handler_invoke(Function& function,
130       buffered_fill_handler<ReadHandler>* this_handler)
131   {
132     boost_asio_handler_invoke_helpers::invoke(
133         function, this_handler->handler_);
134   }
135
136   template <typename Function, typename ReadHandler>
137   inline void asio_handler_invoke(const Function& function,
138       buffered_fill_handler<ReadHandler>* this_handler)
139   {
140     boost_asio_handler_invoke_helpers::invoke(
141         function, this_handler->handler_);
142   }
143
144   template <typename Stream>
145   class initiate_async_buffered_fill
146   {
147   public:
148     typedef typename remove_reference<
149       Stream>::type::lowest_layer_type::executor_type executor_type;
150
151     explicit initiate_async_buffered_fill(Stream& next_layer)
152       : next_layer_(next_layer)
153     {
154     }
155
156     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
157     {
158       return next_layer_.lowest_layer().get_executor();
159     }
160
161     template <typename ReadHandler>
162     void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
163         buffered_stream_storage* storage) const
164     {
165       // If you get an error on the following line it means that your handler
166       // does not meet the documented type requirements for a ReadHandler.
167       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
168
169       non_const_lvalue<ReadHandler> handler2(handler);
170       std::size_t previous_size = storage->size();
171       storage->resize(storage->capacity());
172       next_layer_.async_read_some(
173           buffer(
174             storage->data() + previous_size,
175             storage->size() - previous_size),
176           buffered_fill_handler<typename decay<ReadHandler>::type>(
177             *storage, previous_size, handler2.value));
178     }
179
180   private:
181     Stream& next_layer_;
182   };
183 } // namespace detail
184
185 #if !defined(GENERATING_DOCUMENTATION)
186
187 template <typename ReadHandler, typename Allocator>
188 struct associated_allocator<
189     detail::buffered_fill_handler<ReadHandler>, Allocator>
190 {
191   typedef typename associated_allocator<ReadHandler, Allocator>::type type;
192
193   static type get(const detail::buffered_fill_handler<ReadHandler>& h,
194       const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
195   {
196     return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
197   }
198 };
199
200 template <typename ReadHandler, typename Executor>
201 struct associated_executor<
202     detail::buffered_fill_handler<ReadHandler>, Executor>
203 {
204   typedef typename associated_executor<ReadHandler, Executor>::type type;
205
206   static type get(const detail::buffered_fill_handler<ReadHandler>& h,
207       const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
208   {
209     return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
210   }
211 };
212
213 #endif // !defined(GENERATING_DOCUMENTATION)
214
215 template <typename Stream>
216 template <
217     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
218       std::size_t)) ReadHandler>
219 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
220     void (boost::system::error_code, std::size_t))
221 buffered_read_stream<Stream>::async_fill(
222     BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
223 {
224   return async_initiate<ReadHandler,
225     void (boost::system::error_code, std::size_t)>(
226       detail::initiate_async_buffered_fill<Stream>(next_layer_),
227       handler, &storage_);
228 }
229
230 template <typename Stream>
231 template <typename MutableBufferSequence>
232 std::size_t buffered_read_stream<Stream>::read_some(
233     const MutableBufferSequence& buffers)
234 {
235   using boost::asio::buffer_size;
236   if (buffer_size(buffers) == 0)
237     return 0;
238
239   if (storage_.empty())
240     this->fill();
241
242   return this->copy(buffers);
243 }
244
245 template <typename Stream>
246 template <typename MutableBufferSequence>
247 std::size_t buffered_read_stream<Stream>::read_some(
248     const MutableBufferSequence& buffers, boost::system::error_code& ec)
249 {
250   ec = boost::system::error_code();
251
252   using boost::asio::buffer_size;
253   if (buffer_size(buffers) == 0)
254     return 0;
255
256   if (storage_.empty() && !this->fill(ec))
257     return 0;
258
259   return this->copy(buffers);
260 }
261
262 namespace detail
263 {
264   template <typename MutableBufferSequence, typename ReadHandler>
265   class buffered_read_some_handler
266   {
267   public:
268     buffered_read_some_handler(detail::buffered_stream_storage& storage,
269         const MutableBufferSequence& buffers, ReadHandler& handler)
270       : storage_(storage),
271         buffers_(buffers),
272         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
273     {
274     }
275
276 #if defined(BOOST_ASIO_HAS_MOVE)
277       buffered_read_some_handler(const buffered_read_some_handler& other)
278         : storage_(other.storage_),
279           buffers_(other.buffers_),
280           handler_(other.handler_)
281       {
282       }
283
284       buffered_read_some_handler(buffered_read_some_handler&& other)
285         : storage_(other.storage_),
286           buffers_(other.buffers_),
287           handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
288       {
289       }
290 #endif // defined(BOOST_ASIO_HAS_MOVE)
291
292     void operator()(const boost::system::error_code& ec, std::size_t)
293     {
294       if (ec || storage_.empty())
295       {
296         const std::size_t length = 0;
297         handler_(ec, length);
298       }
299       else
300       {
301         const std::size_t bytes_copied = boost::asio::buffer_copy(
302             buffers_, storage_.data(), storage_.size());
303         storage_.consume(bytes_copied);
304         handler_(ec, bytes_copied);
305       }
306     }
307
308   //private:
309     detail::buffered_stream_storage& storage_;
310     MutableBufferSequence buffers_;
311     ReadHandler handler_;
312   };
313
314   template <typename MutableBufferSequence, typename ReadHandler>
315   inline void* asio_handler_allocate(std::size_t size,
316       buffered_read_some_handler<
317         MutableBufferSequence, ReadHandler>* this_handler)
318   {
319     return boost_asio_handler_alloc_helpers::allocate(
320         size, this_handler->handler_);
321   }
322
323   template <typename MutableBufferSequence, typename ReadHandler>
324   inline void asio_handler_deallocate(void* pointer, std::size_t size,
325       buffered_read_some_handler<
326         MutableBufferSequence, ReadHandler>* this_handler)
327   {
328     boost_asio_handler_alloc_helpers::deallocate(
329         pointer, size, this_handler->handler_);
330   }
331
332   template <typename MutableBufferSequence, typename ReadHandler>
333   inline bool asio_handler_is_continuation(
334       buffered_read_some_handler<
335         MutableBufferSequence, ReadHandler>* this_handler)
336   {
337     return boost_asio_handler_cont_helpers::is_continuation(
338           this_handler->handler_);
339   }
340
341   template <typename Function, typename MutableBufferSequence,
342       typename ReadHandler>
343   inline void asio_handler_invoke(Function& function,
344       buffered_read_some_handler<
345         MutableBufferSequence, ReadHandler>* this_handler)
346   {
347     boost_asio_handler_invoke_helpers::invoke(
348         function, this_handler->handler_);
349   }
350
351   template <typename Function, typename MutableBufferSequence,
352       typename ReadHandler>
353   inline void asio_handler_invoke(const Function& function,
354       buffered_read_some_handler<
355         MutableBufferSequence, ReadHandler>* this_handler)
356   {
357     boost_asio_handler_invoke_helpers::invoke(
358         function, this_handler->handler_);
359   }
360
361   template <typename Stream>
362   class initiate_async_buffered_read_some
363   {
364   public:
365     typedef typename remove_reference<
366       Stream>::type::lowest_layer_type::executor_type executor_type;
367
368     explicit initiate_async_buffered_read_some(Stream& next_layer)
369       : next_layer_(next_layer)
370     {
371     }
372
373     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
374     {
375       return next_layer_.lowest_layer().get_executor();
376     }
377
378     template <typename ReadHandler, typename MutableBufferSequence>
379     void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
380         buffered_stream_storage* storage,
381         const MutableBufferSequence& buffers) const
382     {
383       // If you get an error on the following line it means that your handler
384       // does not meet the documented type requirements for a ReadHandler.
385       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
386
387       using boost::asio::buffer_size;
388       non_const_lvalue<ReadHandler> handler2(handler);
389       if (buffer_size(buffers) == 0 || !storage->empty())
390       {
391         next_layer_.async_read_some(BOOST_ASIO_MUTABLE_BUFFER(0, 0),
392             buffered_read_some_handler<MutableBufferSequence,
393               typename decay<ReadHandler>::type>(
394                 *storage, buffers, handler2.value));
395       }
396       else
397       {
398         initiate_async_buffered_fill<Stream>(this->next_layer_)(
399             buffered_read_some_handler<MutableBufferSequence,
400               typename decay<ReadHandler>::type>(
401                 *storage, buffers, handler2.value),
402             storage);
403       }
404     }
405
406   private:
407     Stream& next_layer_;
408   };
409 } // namespace detail
410
411 #if !defined(GENERATING_DOCUMENTATION)
412
413 template <typename MutableBufferSequence,
414     typename ReadHandler, typename Allocator>
415 struct associated_allocator<
416     detail::buffered_read_some_handler<MutableBufferSequence, ReadHandler>,
417     Allocator>
418 {
419   typedef typename associated_allocator<ReadHandler, Allocator>::type type;
420
421   static type get(
422       const detail::buffered_read_some_handler<
423         MutableBufferSequence, ReadHandler>& h,
424       const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
425   {
426     return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
427   }
428 };
429
430 template <typename MutableBufferSequence,
431     typename ReadHandler, typename Executor>
432 struct associated_executor<
433     detail::buffered_read_some_handler<MutableBufferSequence, ReadHandler>,
434     Executor>
435 {
436   typedef typename associated_executor<ReadHandler, Executor>::type type;
437
438   static type get(
439       const detail::buffered_read_some_handler<
440         MutableBufferSequence, ReadHandler>& h,
441       const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
442   {
443     return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
444   }
445 };
446
447 #endif // !defined(GENERATING_DOCUMENTATION)
448
449 template <typename Stream>
450 template <typename MutableBufferSequence,
451     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
452       std::size_t)) ReadHandler>
453 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
454     void (boost::system::error_code, std::size_t))
455 buffered_read_stream<Stream>::async_read_some(
456     const MutableBufferSequence& buffers,
457     BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
458 {
459   return async_initiate<ReadHandler,
460     void (boost::system::error_code, std::size_t)>(
461       detail::initiate_async_buffered_read_some<Stream>(next_layer_),
462       handler, &storage_, buffers);
463 }
464
465 template <typename Stream>
466 template <typename MutableBufferSequence>
467 std::size_t buffered_read_stream<Stream>::peek(
468     const MutableBufferSequence& buffers)
469 {
470   if (storage_.empty())
471     this->fill();
472   return this->peek_copy(buffers);
473 }
474
475 template <typename Stream>
476 template <typename MutableBufferSequence>
477 std::size_t buffered_read_stream<Stream>::peek(
478     const MutableBufferSequence& buffers, boost::system::error_code& ec)
479 {
480   ec = boost::system::error_code();
481   if (storage_.empty() && !this->fill(ec))
482     return 0;
483   return this->peek_copy(buffers);
484 }
485
486 } // namespace asio
487 } // namespace boost
488
489 #include <boost/asio/detail/pop_options.hpp>
490
491 #endif // BOOST_ASIO_IMPL_BUFFERED_READ_STREAM_HPP