Differences From Artifact [e5256c18dc]:
- File src/OFStream.h — part of check-in [cf93ca4b21] at 2018-09-24 22:14:08 on branch trunk — OFStream: Allow specifying the run loop mode (user: js, size: 51817) [annotate] [blame] [check-ins using]
To Artifact [aea2292c00]:
- File
src/OFStream.h
— part of check-in
[d16ad96cbd]
at
2018-12-07 01:33:47
on branch trunk
— OFStream: Use a delegate for async operations
The target / selector approach had several drawbacks:
* It was inconvenient to use, as for every read or write, a target,
selector and context would need to be specified.
* It lacked any kind of type-safety and would not even warn about using
a callback method with the wrong number of parameters.
* It encouraged using a different callback method for each read or
write call, which results in code that is hard to follow and also
slower (as it needs to recreate the async operation with a new
callback every time). (user: js, size: 47919) [annotate] [blame] [check-ins using]
︙ | ︙ | |||
36 37 38 39 40 41 42 | /*! @file */ @class OFStream; @class OFData; #if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_BLOCKS) /*! | | > | > | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | /*! @file */ @class OFStream; @class OFData; #if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_BLOCKS) /*! * @brief A block which is called when data was read asynchronously from a * stream. * * @param stream The stream on which data was read * @param buffer A buffer with the data that has been read * @param length The length of the data that has been read * @param exception An exception which occurred while reading or `nil` on * success * @return A bool whether the same block should be used for the next read */ typedef bool (^of_stream_async_read_block_t)(OF_KINDOF(OFStream *) stream, void *buffer, size_t length, id _Nullable exception); /*! * @brief A block which is called when a line was read asynchronously from a * stream. * * @param stream The stream on which a line was read * @param line The line which has been read or `nil` when the end of stream * occurred * @param exception An exception which occurred while reading or `nil` on * success * @return A bool whether the same block should be used for the next read */ typedef bool (^of_stream_async_read_line_block_t)(OF_KINDOF(OFStream *) stream, OFString *_Nullable line, id _Nullable exception); /*! * @brief A block which is called when data was written asynchronously to a * stream. * * @param stream The stream to which data was written * @param buffer A pointer to the buffer which was written to the stream. This * can be changed to point to a different buffer to be used on the * next write. * @param bytesWritten The number of bytes which have been written. This * matches the length specified on the asynchronous write * if no exception was encountered. * @param exception An exception which occurred while writing or `nil` on * success * @return The length to repeat the write with or 0 if it should not repeat. * The buffer may be changed, so that every time a new buffer and length * can be specified */ typedef size_t (^of_stream_async_write_block_t)(OF_KINDOF(OFStream *) stream, const void *_Nonnull *_Nonnull buffer, size_t bytesWritten, id _Nullable exception); #endif /*! * @protocol OFStreamDelegate OFStream.h ObjFW/OFStream.h * * A delegate for OFStream. */ @protocol OFStreamDelegate <OFObject> @optional /*! * @brief This method is called when data was read asynchronously from the * stream. * * @param stream The stream on which data was read * @param buffer A buffer with the data that has been read * @param length The length of the data that has been read * @return A bool whether the read should be repeated */ - (bool)stream: (OF_KINDOF(OFStream *))stream didReadIntoBuffer: (void *)buffer length: (size_t)length; /*! * @brief This method is called when a line was read asynchronously from the * stream. * * @param stream The stream on which a line was read * @param line The line which has been read or `nil` when the end of stream * occurred * @return A bool whether the read should be repeated */ - (bool)stream: (OF_KINDOF(OFStream *))stream didReadLine: (nullable OFString *)line; /*! * @brief This method is called when data was written asynchronously to the * stream. * * @param stream The stream to which data was written * @param buffer A pointer to the buffer which was written to the stream. This * can be changed to point to a different buffer to be used on the * next write. * @param length The length of the buffer that has been written * @return The length to repeat the write with or 0 if it should not repeat. * The buffer may be changed, so that every time a new buffer and * length can be specified */ - (size_t)stream: (OF_KINDOF(OFStream *))stream didWriteBuffer: (const void *_Nonnull *_Nonnull)buffer length: (size_t)length; /*! * @brief This method is called when an exception occurred during an * asynchronous operation on the stream. * * @param stream The stream for which an exception occurred * @param exception The exception which occurred for the stream */ - (void)stream: (OF_KINDOF(OFStream *))stream didFailWithException: (id)exception; @end /*! * @class OFStream OFStream.h ObjFW/OFStream.h * * @brief A base class for different types of streams. * * @warning Even though the OFCopying protocol is implemented, it does *not* * return an independent copy of the stream, but instead retains it. |
︙ | ︙ | |||
113 114 115 116 117 118 119 120 121 122 123 124 125 126 | #endif char *_Nullable _readBuffer, *_Nullable _readBufferMemory; char *_Nullable _writeBuffer; size_t _readBufferLength, _writeBufferLength; bool _writeBuffered, _waitingForDelimiter; @protected bool _blocking; } /*! * @brief Whether the end of the stream has been reached. */ @property (readonly, nonatomic, getter=isAtEndOfStream) bool atEndOfStream; | > | 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | #endif char *_Nullable _readBuffer, *_Nullable _readBufferMemory; char *_Nullable _writeBuffer; size_t _readBufferLength, _writeBufferLength; bool _writeBuffered, _waitingForDelimiter; @protected bool _blocking; id <OFStreamDelegate> _Nullable _delegate; } /*! * @brief Whether the end of the stream has been reached. */ @property (readonly, nonatomic, getter=isAtEndOfStream) bool atEndOfStream; |
︙ | ︙ | |||
138 139 140 141 142 143 144 145 146 147 148 149 150 151 | * @brief Whether the stream is in blocking mode. * * By default, a stream is in blocking mode. * On Win32, setting this currently only works for sockets! */ @property (nonatomic, getter=isBlocking) bool blocking; /*! * @brief Reads *at most* size bytes from the stream into a buffer. * * On network streams, this might read less than the specified number of bytes. * If you want to read exactly the specified number of bytes, use * @ref readIntoBuffer:exactLength:. Note that a read can even return 0 bytes - * this does not necessarily mean that the stream ended, so you still need to | > > > > > > > > > | 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | * @brief Whether the stream is in blocking mode. * * By default, a stream is in blocking mode. * On Win32, setting this currently only works for sockets! */ @property (nonatomic, getter=isBlocking) bool blocking; /*! * @brief The delegate for asynchronous operations on the stream. * * @note The delegate is retained for as long as asynchronous operations are * still outstanding. */ @property OF_NULLABLE_PROPERTY (assign, nonatomic) id <OFStreamDelegate> delegate; /*! * @brief Reads *at most* size bytes from the stream into a buffer. * * On network streams, this might read less than the specified number of bytes. * If you want to read exactly the specified number of bytes, use * @ref readIntoBuffer:exactLength:. Note that a read can even return 0 bytes - * this does not necessarily mean that the stream ended, so you still need to |
︙ | ︙ | |||
191 192 193 194 195 196 197 | * @note The stream must conform to @ref OFReadyForReadingObserving in order * for this to work! * * @param buffer The buffer into which the data is read. * The buffer must not be freed before the async read completed! * @param length The length of the data that should be read at most. * The buffer *must* be *at least* this big! | < < < < < < < < < < | < < < < < < < < < < < < < | < < < < < < < < < < < < < | < < < < < < < < < < < < < | < < < | 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 | * @note The stream must conform to @ref OFReadyForReadingObserving in order * for this to work! * * @param buffer The buffer into which the data is read. * The buffer must not be freed before the async read completed! * @param length The length of the data that should be read at most. * The buffer *must* be *at least* this big! */ - (void)asyncReadIntoBuffer: (void *)buffer length: (size_t)length; /*! * @brief Asynchronously reads *at most* size bytes from the stream into a * buffer. * * On network streams, this might read less than the specified number of bytes. * If you want to read exactly the specified number of bytes, use * @ref asyncReadIntoBuffer:exactLength:target:selector:context:. Note that a * read can even return 0 bytes - this does not necessarily mean that the * stream ended, so you still need to check @ref atEndOfStream. * * @note The stream must conform to @ref OFReadyForReadingObserving in order * for this to work! * * @param buffer The buffer into which the data is read. * The buffer must not be freed before the async read completed! * @param length The length of the data that should be read at most. * The buffer *must* be *at least* this big! * @param runLoopMode The run loop mode in which to perform the async read */ - (void)asyncReadIntoBuffer: (void *)buffer length: (size_t)length runLoopMode: (of_run_loop_mode_t)runLoopMode; /*! * @brief Asynchronously reads exactly the specified length bytes from the * stream into a buffer. * * Unlike @ref asyncReadIntoBuffer:length:target:selector:context:, this method * does not call the method when less than the specified length has been read - * instead, it waits until it got exactly the specified length, the stream has * ended or an exception occurred. * * @note The stream must conform to @ref OFReadyForReadingObserving in order * for this to work! * * @param buffer The buffer into which the data is read * @param length The length of the data that should be read. * The buffer *must* be *at least* this big! */ - (void)asyncReadIntoBuffer: (void *)buffer exactLength: (size_t)length; /*! * @brief Asynchronously reads exactly the specified length bytes from the * stream into a buffer. * * Unlike @ref asyncReadIntoBuffer:length:target:selector:context:, this method * does not call the method when less than the specified length has been read - * instead, it waits until it got exactly the specified length, the stream has * ended or an exception occurred. * * @note The stream must conform to @ref OFReadyForReadingObserving in order * for this to work! * * @param buffer The buffer into which the data is read * @param length The length of the data that should be read. * The buffer *must* be *at least* this big! * @param runLoopMode The run loop mode in which to perform the async read */ - (void)asyncReadIntoBuffer: (void *)buffer exactLength: (size_t)length runLoopMode: (of_run_loop_mode_t)runLoopMode; # ifdef OF_HAVE_BLOCKS /*! * @brief Asynchronously reads *at most* ref size bytes from the stream into a * buffer. * * On network streams, this might read less than the specified number of bytes. |
︙ | ︙ | |||
774 775 776 777 778 779 780 | #ifdef OF_HAVE_SOCKETS /*! * @brief Asynchronously reads until a newline, `\0`, end of stream or an * exception occurs. * * @note The stream must conform to @ref OFReadyForReadingObserving in order * for this to work! | < < < < < < < < < < | < < < < < < < < < < < | < < < < < < < < < < < < | < < < | 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 | #ifdef OF_HAVE_SOCKETS /*! * @brief Asynchronously reads until a newline, `\0`, end of stream or an * exception occurs. * * @note The stream must conform to @ref OFReadyForReadingObserving in order * for this to work! */ - (void)asyncReadLine; /*! * @brief Asynchronously reads with the specified encoding until a newline, * `\0`, end of stream or an exception occurs. * * @note The stream must conform to @ref OFReadyForReadingObserving in order * for this to work! * * @param encoding The encoding used by the stream */ - (void)asyncReadLineWithEncoding: (of_string_encoding_t)encoding; /*! * @brief Asynchronously reads with the specified encoding until a newline, * `\0`, end of stream or an exception occurs. * * @note The stream must conform to @ref OFReadyForReadingObserving in order * for this to work! * * @param encoding The encoding used by the stream * @param runLoopMode The run loop mode in which to perform the async read */ - (void)asyncReadLineWithEncoding: (of_string_encoding_t)encoding runLoopMode: (of_run_loop_mode_t)runLoopMode; # ifdef OF_HAVE_BLOCKS /*! * @brief Asynchronously reads until a newline, `\0`, end of stream or an * exception occurs. * * @note The stream must conform to @ref OFReadyForReadingObserving in order |
︙ | ︙ | |||
983 984 985 986 987 988 989 | * * @note The stream must conform to @ref OFReadyForWritingObserving in order * for this to work! * * @param buffer The buffer from which the data is written into the stream. The * buffer needs to be valid until the write request is completed! * @param length The length of the data that should be written | < < < < < < < < < < < < | < < < < < < < < < < < < < < < | < < < | 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 | * * @note The stream must conform to @ref OFReadyForWritingObserving in order * for this to work! * * @param buffer The buffer from which the data is written into the stream. The * buffer needs to be valid until the write request is completed! * @param length The length of the data that should be written */ - (void)asyncWriteBuffer: (const void *)buffer length: (size_t)length; /*! * @brief Asynchronously writes a buffer into the stream. * * @note The stream must conform to @ref OFReadyForWritingObserving in order * for this to work! * * @param buffer The buffer from which the data is written into the stream. The * buffer needs to be valid until the write request is completed! * @param length The length of the data that should be written * @param runLoopMode The run loop mode in which to perform the async write */ - (void)asyncWriteBuffer: (const void *)buffer length: (size_t)length runLoopMode: (of_run_loop_mode_t)runLoopMode; # ifdef OF_HAVE_BLOCKS /*! * @brief Asynchronously writes a buffer into the stream. * * @note The stream must conform to @ref OFReadyForWritingObserving in order * for this to work! |
︙ | ︙ |