1 | // |
2 | // completion_condition.hpp |
3 | // ~~~~~~~~~~~~~~~~~~~~~~~~ |
4 | // |
5 | // Copyright (c) 2003-2024 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). |
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). |
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> |
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 | |
63 | explicit transfer_at_least_t(std::size_t minimum) |
64 | : minimum_(minimum) |
65 | { |
66 | } |
67 | |
68 | template <typename Error> |
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 | |
84 | explicit transfer_exactly_t(std::size_t size) |
85 | : size_(size) |
86 | { |
87 | } |
88 | |
89 | template <typename Error> |
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 |
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 |
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 |
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 | |