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