1 //
2 // completion_condition.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2018 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 ASIO_COMPLETION_CONDITION_HPP
12 #define ASIO_COMPLETION_CONDITION_HPP
13 
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17 
18 #include "asio/detail/config.hpp"
19 #include <cstddef>
20 
21 #include "asio/detail/push_options.hpp"
22 
23 namespace asio {
24 
25 namespace detail {
26 
27 // The default maximum number of bytes to transfer in a single operation.
28 enum default_max_transfer_size_t { default_max_transfer_size = 65536 };
29 
30 // Adapt result of old-style completion conditions (which had a bool result
31 // where true indicated that the operation was complete).
adapt_completion_condition_result(bool result)32 inline std::size_t adapt_completion_condition_result(bool result)
33 {
34   return result ? 0 : default_max_transfer_size;
35 }
36 
37 // Adapt result of current completion conditions (which have a size_t result
38 // where 0 means the operation is complete, and otherwise the result is the
39 // maximum number of bytes to transfer on the next underlying operation).
adapt_completion_condition_result(std::size_t result)40 inline std::size_t adapt_completion_condition_result(std::size_t result)
41 {
42   return result;
43 }
44 
45 class transfer_all_t
46 {
47 public:
48   typedef std::size_t result_type;
49 
50   template <typename Error>
operator ()(const Error & err,std::size_t)51   std::size_t operator()(const Error& err, std::size_t)
52   {
53     return !!err ? 0 : default_max_transfer_size;
54   }
55 };
56 
57 class transfer_at_least_t
58 {
59 public:
60   typedef std::size_t result_type;
61 
transfer_at_least_t(std::size_t minimum)62   explicit transfer_at_least_t(std::size_t minimum)
63     : minimum_(minimum)
64   {
65   }
66 
67   template <typename Error>
operator ()(const Error & err,std::size_t bytes_transferred)68   std::size_t operator()(const Error& err, std::size_t bytes_transferred)
69   {
70     return (!!err || bytes_transferred >= minimum_)
71       ? 0 : default_max_transfer_size;
72   }
73 
74 private:
75   std::size_t minimum_;
76 };
77 
78 class transfer_exactly_t
79 {
80 public:
81   typedef std::size_t result_type;
82 
transfer_exactly_t(std::size_t size)83   explicit transfer_exactly_t(std::size_t size)
84     : size_(size)
85   {
86   }
87 
88   template <typename Error>
operator ()(const Error & err,std::size_t bytes_transferred)89   std::size_t operator()(const Error& err, std::size_t bytes_transferred)
90   {
91     return (!!err || bytes_transferred >= size_) ? 0 :
92       (size_ - bytes_transferred < default_max_transfer_size
93         ? size_ - bytes_transferred : std::size_t(default_max_transfer_size));
94   }
95 
96 private:
97   std::size_t size_;
98 };
99 
100 } // namespace detail
101 
102 /**
103  * @defgroup completion_condition Completion Condition Function Objects
104  *
105  * Function objects used for determining when a read or write operation should
106  * complete.
107  */
108 /*@{*/
109 
110 /// Return a completion condition function object that indicates that a read or
111 /// write operation should continue until all of the data has been transferred,
112 /// or until an error occurs.
113 /**
114  * This function is used to create an object, of unspecified type, that meets
115  * CompletionCondition requirements.
116  *
117  * @par Example
118  * Reading until a buffer is full:
119  * @code
120  * boost::array<char, 128> buf;
121  * asio::error_code ec;
122  * std::size_t n = asio::read(
123  *     sock, asio::buffer(buf),
124  *     asio::transfer_all(), ec);
125  * if (ec)
126  * {
127  *   // An error occurred.
128  * }
129  * else
130  * {
131  *   // n == 128
132  * }
133  * @endcode
134  */
135 #if defined(GENERATING_DOCUMENTATION)
136 unspecified transfer_all();
137 #else
transfer_all()138 inline detail::transfer_all_t transfer_all()
139 {
140   return detail::transfer_all_t();
141 }
142 #endif
143 
144 /// Return a completion condition function object that indicates that a read or
145 /// write operation should continue until a minimum number of bytes has been
146 /// transferred, or until an error occurs.
147 /**
148  * This function is used to create an object, of unspecified type, that meets
149  * CompletionCondition requirements.
150  *
151  * @par Example
152  * Reading until a buffer is full or contains at least 64 bytes:
153  * @code
154  * boost::array<char, 128> buf;
155  * asio::error_code ec;
156  * std::size_t n = asio::read(
157  *     sock, asio::buffer(buf),
158  *     asio::transfer_at_least(64), ec);
159  * if (ec)
160  * {
161  *   // An error occurred.
162  * }
163  * else
164  * {
165  *   // n >= 64 && n <= 128
166  * }
167  * @endcode
168  */
169 #if defined(GENERATING_DOCUMENTATION)
170 unspecified transfer_at_least(std::size_t minimum);
171 #else
transfer_at_least(std::size_t minimum)172 inline detail::transfer_at_least_t transfer_at_least(std::size_t minimum)
173 {
174   return detail::transfer_at_least_t(minimum);
175 }
176 #endif
177 
178 /// Return a completion condition function object that indicates that a read or
179 /// write operation should continue until an exact number of bytes has been
180 /// transferred, or until an error occurs.
181 /**
182  * This function is used to create an object, of unspecified type, that meets
183  * CompletionCondition requirements.
184  *
185  * @par Example
186  * Reading until a buffer is full or contains exactly 64 bytes:
187  * @code
188  * boost::array<char, 128> buf;
189  * asio::error_code ec;
190  * std::size_t n = asio::read(
191  *     sock, asio::buffer(buf),
192  *     asio::transfer_exactly(64), ec);
193  * if (ec)
194  * {
195  *   // An error occurred.
196  * }
197  * else
198  * {
199  *   // n == 64
200  * }
201  * @endcode
202  */
203 #if defined(GENERATING_DOCUMENTATION)
204 unspecified transfer_exactly(std::size_t size);
205 #else
transfer_exactly(std::size_t size)206 inline detail::transfer_exactly_t transfer_exactly(std::size_t size)
207 {
208   return detail::transfer_exactly_t(size);
209 }
210 #endif
211 
212 /*@}*/
213 
214 } // namespace asio
215 
216 #include "asio/detail/pop_options.hpp"
217 
218 #endif // ASIO_COMPLETION_CONDITION_HPP
219