| 1 | #ifndef MP_IOS_RW_H__ |
|---|
| 2 | #define MP_IOS_RW_H__ |
|---|
| 3 | |
|---|
| 4 | #include <unistd.h> |
|---|
| 5 | #include <errno.h> |
|---|
| 6 | |
|---|
| 7 | namespace mp { |
|---|
| 8 | namespace ios { |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | template <typename IO, typename Callback> |
|---|
| 12 | struct iosf_read : ios { |
|---|
| 13 | iosf_read(IO& _io, void* _buf, size_t _buflen, Callback _callback) : |
|---|
| 14 | io(_io), buf((char*)_buf), buflen(_buflen), callback(_callback) {} |
|---|
| 15 | ~iosf_read() {} |
|---|
| 16 | next_t operator() (int fd, short event) |
|---|
| 17 | { |
|---|
| 18 | ssize_t rl; |
|---|
| 19 | if( (rl = read(fd, buf, buflen)) < 0 ) { |
|---|
| 20 | if( errno == EAGAIN || errno == EINTR ) { return MP_IOS_CONTINUE; } |
|---|
| 21 | int err = callback(io, errno, fd, buf, buflen, static_cast<size_t>(rl)); |
|---|
| 22 | return MP_IOS_END(err); |
|---|
| 23 | } |
|---|
| 24 | int err = callback(io, 0, fd, buf, buflen, static_cast<size_t>(rl)); |
|---|
| 25 | return MP_IOS_END(err); |
|---|
| 26 | } |
|---|
| 27 | private: |
|---|
| 28 | IO& io; |
|---|
| 29 | char* buf; |
|---|
| 30 | size_t buflen; |
|---|
| 31 | ios_callback<int (IO&, int, int, char*, size_t, size_t), Callback> callback; |
|---|
| 32 | }; |
|---|
| 33 | |
|---|
| 34 | template <typename IO, typename Callback> |
|---|
| 35 | int ios_read(IO& io, int fd, void* buf, size_t buflen, Callback callback) |
|---|
| 36 | { |
|---|
| 37 | typedef iosf_read<IO, Callback> IOS; |
|---|
| 38 | return MP_IOS_ADD(io, IOS, &IOS::operator(), |
|---|
| 39 | fd, EV_READ, IOS(io, buf, buflen, callback)); |
|---|
| 40 | } |
|---|
| 41 | |
|---|
| 42 | |
|---|
| 43 | template <typename IO, typename Callback> |
|---|
| 44 | struct iosf_read_at_least : ios { |
|---|
| 45 | iosf_read_at_least(IO& _io, void* _buf, size_t _buflen, |
|---|
| 46 | size_t _minlen, Callback _callback) : |
|---|
| 47 | io(_io), buf((char*)_buf), current(_buf), buflen(_buflen), |
|---|
| 48 | rest(_buflen), minlen(_minlen), callback(_callback) {} |
|---|
| 49 | next_t operator() (int fd, short event) |
|---|
| 50 | { |
|---|
| 51 | ssize_t rl; |
|---|
| 52 | if( (rl = read(fd, current, rest)) < 0 ) { |
|---|
| 53 | if( errno == EAGAIN || errno == EINTR ) { return MP_IOS_CONTINUE; } |
|---|
| 54 | int err = callback(io, errno, fd, buf, buflen, |
|---|
| 55 | minlen, current - buf); |
|---|
| 56 | return MP_IOS_END(err); |
|---|
| 57 | } |
|---|
| 58 | if( rl == 0 ) { |
|---|
| 59 | int err = callback(io, 0, fd, buf, buflen, |
|---|
| 60 | minlen, current - buf); |
|---|
| 61 | return MP_IOS_END(err); |
|---|
| 62 | } |
|---|
| 63 | current += rl; |
|---|
| 64 | if( rest <= rl ) { |
|---|
| 65 | int err = callback(io, 0, fd, buf, buflen, |
|---|
| 66 | minlen, current - buf); |
|---|
| 67 | return MP_IOS_END(err); |
|---|
| 68 | } |
|---|
| 69 | rest -= rl; |
|---|
| 70 | return MP_IOS_CONTINUE; |
|---|
| 71 | } |
|---|
| 72 | private: |
|---|
| 73 | IO& io; |
|---|
| 74 | char* buf; |
|---|
| 75 | char* current; |
|---|
| 76 | size_t buflen; |
|---|
| 77 | size_t rest; |
|---|
| 78 | size_t minlen; |
|---|
| 79 | ios_callback<int (IO&, int, int, char*, size_t), Callback> callback; |
|---|
| 80 | }; |
|---|
| 81 | |
|---|
| 82 | template <typename IO, typename Callback> |
|---|
| 83 | int ios_read_at_least(IO& io, int fd, void* buf, size_t buflen, |
|---|
| 84 | size_t minlen, Callback callback) |
|---|
| 85 | { |
|---|
| 86 | typedef iosf_read_at_least<IO, Callback> IOS; |
|---|
| 87 | return MP_IOS_ADD(io, IOS, &IOS::operator(), |
|---|
| 88 | fd, EV_READ, IOS(io, buf, buflen, minlen, callback)); |
|---|
| 89 | } |
|---|
| 90 | |
|---|
| 91 | |
|---|
| 92 | template <typename IO, typename Callback> |
|---|
| 93 | struct iosf_read_at_most : ios { |
|---|
| 94 | iosf_read_at_most(IO& _io, void* _buf, size_t _buflen, |
|---|
| 95 | size_t _maxlen, Callback _callback) : |
|---|
| 96 | io(_io), buf((char*)_buf), buflen(_buflen), |
|---|
| 97 | maxlen(_maxlen), callback(_callback) {} |
|---|
| 98 | next_t operator() (int fd, short event) |
|---|
| 99 | { |
|---|
| 100 | ssize_t rl; |
|---|
| 101 | if( (rl = read(fd, buf, maxlen)) < 0 ) { |
|---|
| 102 | if( errno == EAGAIN || errno == EINTR ) { return MP_IOS_CONTINUE; } |
|---|
| 103 | int err = callback(io, errno, fd, buf, buflen, |
|---|
| 104 | maxlen, static_cast<size_t>(rl)); |
|---|
| 105 | return MP_IOS_END(err); |
|---|
| 106 | } |
|---|
| 107 | int err = callback(io, 0, fd, buf, buflen, |
|---|
| 108 | maxlen, static_cast<size_t>(rl)); |
|---|
| 109 | return MP_IOS_END(err); |
|---|
| 110 | } |
|---|
| 111 | private: |
|---|
| 112 | IO& io; |
|---|
| 113 | char* buf; |
|---|
| 114 | size_t buflen; |
|---|
| 115 | size_t maxlen; |
|---|
| 116 | ios_callback<int (IO&, int, int, char*, size_t, size_t), Callback> callback; |
|---|
| 117 | }; |
|---|
| 118 | |
|---|
| 119 | template <typename IO, typename Callback> |
|---|
| 120 | int ios_read_at_most(IO& io, int fd, void* buf, size_t buflen, |
|---|
| 121 | size_t maxlen, Callback callback) |
|---|
| 122 | { |
|---|
| 123 | return io.add( fd, |
|---|
| 124 | EV_READ, |
|---|
| 125 | iosf_read_at_most<IO, Callback>(io, buf, buflen, |
|---|
| 126 | maxlen, callback) ); |
|---|
| 127 | } |
|---|
| 128 | |
|---|
| 129 | |
|---|
| 130 | |
|---|
| 131 | template <typename IO, typename Callback> |
|---|
| 132 | struct iosf_read_just : ios { |
|---|
| 133 | iosf_read_just(IO& _io, void* _buf, size_t _len, Callback _callback) : |
|---|
| 134 | io(_io), buf((char*)_buf), current((char*)_buf), rest(_len), |
|---|
| 135 | callback(_callback) {} |
|---|
| 136 | next_t operator() (int fd, short event) |
|---|
| 137 | { |
|---|
| 138 | ssize_t rl; |
|---|
| 139 | if( (rl = read(fd, current, rest)) < 0 ) { |
|---|
| 140 | if( errno == EAGAIN ) { |
|---|
| 141 | return MP_IOS_CONTINUE; |
|---|
| 142 | } |
|---|
| 143 | size_t reached = current - buf; |
|---|
| 144 | int err = callback(io, fd, buf, reached + rest, reached); |
|---|
| 145 | return MP_IOS_END(err); |
|---|
| 146 | } |
|---|
| 147 | if( rl == 0 ) { |
|---|
| 148 | size_t reached = current - buf; |
|---|
| 149 | int err = callback(io, fd, buf, reached + rest, reached); |
|---|
| 150 | return MP_IOS_END(err); |
|---|
| 151 | } |
|---|
| 152 | if( rest <= (size_t)rl ) { |
|---|
| 153 | size_t reached = current - buf + rl; |
|---|
| 154 | int err = callback(io, fd, buf, reached, reached); |
|---|
| 155 | return MP_IOS_END(err); |
|---|
| 156 | } |
|---|
| 157 | rest -= rl; |
|---|
| 158 | current += rl; |
|---|
| 159 | return MP_IOS_CONTINUE; |
|---|
| 160 | } |
|---|
| 161 | private: |
|---|
| 162 | IO& io; |
|---|
| 163 | char* buf; |
|---|
| 164 | char* current; |
|---|
| 165 | size_t rest; |
|---|
| 166 | ios_callback<int (IO&, int, char*, size_t, size_t), Callback> callback; |
|---|
| 167 | }; |
|---|
| 168 | |
|---|
| 169 | template <typename IO, typename Callback> |
|---|
| 170 | int ios_read_just(IO& io, int fd, void* buf, size_t len, Callback callback) |
|---|
| 171 | { |
|---|
| 172 | typedef iosf_read_just<IO, Callback> IOS; |
|---|
| 173 | return MP_IOS_ADD(io, IOS, &IOS::operator(), |
|---|
| 174 | fd, EV_READ, IOS(io, buf, len, callback)); |
|---|
| 175 | } |
|---|
| 176 | |
|---|
| 177 | /* =================================== */ |
|---|
| 178 | |
|---|
| 179 | |
|---|
| 180 | template <typename IO, typename Callback> |
|---|
| 181 | struct iosf_write : ios { |
|---|
| 182 | iosf_write(IO& _io, void* _buf, size_t _buflen, Callback _callback) : |
|---|
| 183 | io(_io), buf((char*)_buf), buflen(_buflen), callback(_callback) {} |
|---|
| 184 | next_t operator() (int fd, short event) |
|---|
| 185 | { |
|---|
| 186 | ssize_t rl; |
|---|
| 187 | if( (rl = write(fd, buf, buflen)) < 0 ) { |
|---|
| 188 | if( errno == EAGAIN || errno == EINTR ) { return MP_IOS_CONTINUE; } |
|---|
| 189 | int err = callback(io, errno, fd, buf, buflen, static_cast<size_t>(rl)); |
|---|
| 190 | return MP_IOS_END(err); |
|---|
| 191 | } |
|---|
| 192 | int err = callback(io, 0, fd, buf, buflen, static_cast<size_t>(rl)); |
|---|
| 193 | return MP_IOS_END(err); |
|---|
| 194 | } |
|---|
| 195 | private: |
|---|
| 196 | IO& io; |
|---|
| 197 | char* buf; |
|---|
| 198 | size_t buflen; |
|---|
| 199 | ios_callback<int (IO&, int, int, char*, size_t, size_t), Callback> callback; |
|---|
| 200 | }; |
|---|
| 201 | |
|---|
| 202 | template <typename IO, typename Callback> |
|---|
| 203 | int ios_write(IO& io, int fd, void* buf, size_t buflen, Callback callback) |
|---|
| 204 | { |
|---|
| 205 | return io.add( fd, |
|---|
| 206 | EV_WRITE, |
|---|
| 207 | iosf_write<IO, Callback>(io, buf, buflen, callback) ); |
|---|
| 208 | } |
|---|
| 209 | |
|---|
| 210 | |
|---|
| 211 | |
|---|
| 212 | template <typename IO, typename Callback> |
|---|
| 213 | struct iosf_write_at_least : ios { |
|---|
| 214 | iosf_write_at_least(IO& _io, void* _buf, size_t _buflen, |
|---|
| 215 | size_t _minlen, Callback _callback) : |
|---|
| 216 | io(_io), buf((char*)_buf), current(_buf), buflen(_buflen), |
|---|
| 217 | rest(_buflen), minlen(_minlen), callback(_callback) {} |
|---|
| 218 | next_t operator() (int fd, short event) |
|---|
| 219 | { |
|---|
| 220 | ssize_t rl; |
|---|
| 221 | if( (rl = write(fd, current, rest)) < 0 ) { |
|---|
| 222 | if( errno == EAGAIN || errno == EINTR ) { return MP_IOS_CONTINUE; } |
|---|
| 223 | int err = callback(io, errno, fd, buf, buflen, |
|---|
| 224 | minlen, current - buf); |
|---|
| 225 | return MP_IOS_END(err); |
|---|
| 226 | } |
|---|
| 227 | if( rl == 0 ) { |
|---|
| 228 | int err = callback(io, 0, fd, buf, buflen, |
|---|
| 229 | minlen, current - buf); |
|---|
| 230 | return MP_IOS_END(err); |
|---|
| 231 | } |
|---|
| 232 | current += rl; |
|---|
| 233 | if( rest <= rl ) { |
|---|
| 234 | int err = callback(io, 0, fd, buf, buflen, |
|---|
| 235 | minlen, current - buf); |
|---|
| 236 | return MP_IOS_END(err); |
|---|
| 237 | } |
|---|
| 238 | rest -= rl; |
|---|
| 239 | return MP_IOS_CONTINUE; |
|---|
| 240 | } |
|---|
| 241 | private: |
|---|
| 242 | IO& io; |
|---|
| 243 | char* buf; |
|---|
| 244 | char* current; |
|---|
| 245 | size_t buflen; |
|---|
| 246 | size_t rest; |
|---|
| 247 | size_t minlen; |
|---|
| 248 | ios_callback<int (IO&, int, int, char*, size_t), Callback> callback; |
|---|
| 249 | }; |
|---|
| 250 | |
|---|
| 251 | |
|---|
| 252 | template <typename IO, typename Callback> |
|---|
| 253 | int ios_write_at_least(IO& io, int fd, void* buf, size_t buflen, |
|---|
| 254 | size_t minlen, Callback callback) |
|---|
| 255 | { |
|---|
| 256 | return io.add( fd, |
|---|
| 257 | EV_WRITE, |
|---|
| 258 | iosf_write_at_least<IO, Callback>(io, buf, buflen, |
|---|
| 259 | minlen, callback) |
|---|
| 260 | ); |
|---|
| 261 | } |
|---|
| 262 | |
|---|
| 263 | |
|---|
| 264 | template <typename IO, typename Callback> |
|---|
| 265 | struct iosf_write_at_most : ios { |
|---|
| 266 | iosf_write_at_most(IO& _io, void* _buf, size_t _buflen, |
|---|
| 267 | size_t _maxlen, Callback _callback) : |
|---|
| 268 | io(_io), buf((char*)_buf), buflen(_buflen), |
|---|
| 269 | maxlen(_maxlen), callback(_callback) {} |
|---|
| 270 | next_t operator() (int fd, short event) |
|---|
| 271 | { |
|---|
| 272 | ssize_t rl; |
|---|
| 273 | if( (rl = write(fd, buf, maxlen)) < 0 ) { |
|---|
| 274 | if( errno == EAGAIN || errno == EINTR ) { return MP_IOS_CONTINUE; } |
|---|
| 275 | int err = callback(io, errno, fd, buf, buflen, |
|---|
| 276 | maxlen, static_cast<size_t>(rl)); |
|---|
| 277 | return MP_IOS_END(err); |
|---|
| 278 | } |
|---|
| 279 | int err = callback(io, 0, fd, buf, buflen, |
|---|
| 280 | maxlen, static_cast<size_t>(rl)); |
|---|
| 281 | return MP_IOS_END(err); |
|---|
| 282 | } |
|---|
| 283 | private: |
|---|
| 284 | IO& io; |
|---|
| 285 | char* buf; |
|---|
| 286 | size_t buflen; |
|---|
| 287 | size_t maxlen; |
|---|
| 288 | ios_callback<int (IO&, int, int, char*, size_t, size_t), Callback> callback; |
|---|
| 289 | }; |
|---|
| 290 | |
|---|
| 291 | template <typename IO, typename Callback> |
|---|
| 292 | int ios_write_at_most(IO& io, int fd, void* buf, size_t buflen, |
|---|
| 293 | size_t maxlen, Callback callback) |
|---|
| 294 | { |
|---|
| 295 | return io.add( fd, |
|---|
| 296 | EV_WRITE, |
|---|
| 297 | iosf_write_at_most<IO, Callback>(io, buf, buflen, |
|---|
| 298 | maxlen, callback) ); |
|---|
| 299 | } |
|---|
| 300 | |
|---|
| 301 | |
|---|
| 302 | |
|---|
| 303 | template <typename IO, typename Callback> |
|---|
| 304 | struct iosf_write_just : ios { |
|---|
| 305 | iosf_write_just(IO& _io, void* _buf, size_t _len, Callback _callback) : |
|---|
| 306 | io(_io), buf((char*)_buf), current((char*)_buf), rest(_len), |
|---|
| 307 | callback(_callback) {} |
|---|
| 308 | next_t operator() (int fd, short event) |
|---|
| 309 | { |
|---|
| 310 | ssize_t rl; |
|---|
| 311 | if( (rl = write(fd, current, rest)) < 0 ) { |
|---|
| 312 | if( errno == EAGAIN ) { |
|---|
| 313 | return MP_IOS_CONTINUE; |
|---|
| 314 | } |
|---|
| 315 | size_t reached = current - buf; |
|---|
| 316 | int err = callback(io, fd, buf, reached + rest, reached); |
|---|
| 317 | return MP_IOS_END(err); |
|---|
| 318 | } |
|---|
| 319 | if( rl == 0 ) { |
|---|
| 320 | size_t reached = current - buf; |
|---|
| 321 | int err = callback(io, fd, buf, reached + rest, reached); |
|---|
| 322 | return MP_IOS_END(err); |
|---|
| 323 | } |
|---|
| 324 | if( rest <= (size_t)rl ) { |
|---|
| 325 | size_t reached = current - buf + rl; |
|---|
| 326 | int err = callback(io, fd, buf, reached, reached); |
|---|
| 327 | return MP_IOS_END(err); |
|---|
| 328 | } |
|---|
| 329 | rest -= rl; |
|---|
| 330 | current += rl; |
|---|
| 331 | return MP_IOS_CONTINUE; |
|---|
| 332 | } |
|---|
| 333 | private: |
|---|
| 334 | IO& io; |
|---|
| 335 | char* buf; |
|---|
| 336 | char* current; |
|---|
| 337 | size_t rest; |
|---|
| 338 | ios_callback<int (IO&, int, char*, size_t, size_t), Callback> callback; |
|---|
| 339 | }; |
|---|
| 340 | |
|---|
| 341 | template <typename IO, typename Callback> |
|---|
| 342 | int ios_write_just(IO& io, int fd, void* buf, size_t len, Callback callback) |
|---|
| 343 | { |
|---|
| 344 | typedef iosf_write_just<IO, Callback> IOS; |
|---|
| 345 | return MP_IOS_ADD(io, IOS, &IOS::operator(), |
|---|
| 346 | fd, EV_WRITE, IOS(io, buf, len, callback)); |
|---|
| 347 | } |
|---|
| 348 | |
|---|
| 349 | |
|---|
| 350 | |
|---|
| 351 | } // namespace ios |
|---|
| 352 | } // namespace mp |
|---|
| 353 | |
|---|
| 354 | #endif /* mp/ios/rw.h */ |
|---|
| 355 | |
|---|