@@ -111,17 +111,29 @@ # endif of_string_encoding_t _encoding; } @end -@interface OFRunLoop_WriteQueueItem: OFRunLoop_QueueItem +@interface OFRunLoop_WriteDataQueueItem: OFRunLoop_QueueItem +{ +@public +# ifdef OF_HAVE_BLOCKS + of_stream_async_write_data_block_t _block; +# endif + OFData *_data; + size_t _writtenLength; +} +@end + +@interface OFRunLoop_WriteStringQueueItem: OFRunLoop_QueueItem { @public # ifdef OF_HAVE_BLOCKS - of_stream_async_write_block_t _block; + of_stream_async_write_string_block_t _block; # endif - OFData *_data; + OFString *_string; + of_string_encoding_t _encoding; size_t _writtenLength; } @end @interface OFRunLoop_ConnectQueueItem: OFRunLoop_QueueItem @@ -248,12 +260,11 @@ { /* * Retain the queue so that it doesn't disappear from us because the * handler called -[cancelAsyncRequests]. */ - OFList OF_GENERIC(OF_KINDOF(OFRunLoop_WriteQueueItem *)) *queue = - [[_writeQueues objectForKey: object] retain]; + OFList *queue = [[_writeQueues objectForKey: object] retain]; assert(queue != nil); @try { if (![[queue firstObject] handleObject: object]) { @@ -444,11 +455,11 @@ [super dealloc]; } # endif @end -@implementation OFRunLoop_WriteQueueItem +@implementation OFRunLoop_WriteDataQueueItem - (bool)handleObject: (id)object { size_t length; id exception = nil; size_t dataLength = [_data count] * [_data itemSize]; @@ -511,10 +522,84 @@ { [_data release]; # ifdef OF_HAVE_BLOCKS [_block release]; # endif + + [super dealloc]; +} +@end + +@implementation OFRunLoop_WriteStringQueueItem +- (bool)handleObject: (id)object +{ + size_t length; + id exception = nil; + size_t cStringLength = [_string cStringLengthWithEncoding: _encoding]; + OFString *newString, *oldString; + + @try { + const char *cString = [_string cStringWithEncoding: _encoding]; + + length = [object writeBuffer: cString + _writtenLength + length: cStringLength - _writtenLength]; + } @catch (id e) { + length = 0; + exception = e; + } + + _writtenLength += length; + + if (_writtenLength != cStringLength && exception == nil) + return true; + +# ifdef OF_HAVE_BLOCKS + if (_block != NULL) { + newString = _block(object, _string, _encoding, _writtenLength, + exception); + + if (newString == nil) + return false; + + oldString = _string; + _string = [newString copy]; + [oldString release]; + + _writtenLength = 0; + return true; + } else { +# endif + if (![_delegate respondsToSelector: @selector(stream: + didWriteString:encoding:bytesWritten:exception:)]) + return false; + + newString = [_delegate stream: object + didWriteString: _string + encoding: _encoding + bytesWritten: _writtenLength + exception: exception]; + + if (newString == nil) + return false; + + oldString = _string; + _string = [newString copy]; + [oldString release]; + + _writtenLength = 0; + return true; +# ifdef OF_HAVE_BLOCKS + } +# endif +} + +- (void)dealloc +{ + [_string release]; +# ifdef OF_HAVE_BLOCKS + [_block release]; +# endif [super dealloc]; } @end @@ -787,15 +872,29 @@ stream data: (OFData *)data mode: (of_run_loop_mode_t)mode delegate: (id )delegate { - ADD_WRITE(OFRunLoop_WriteQueueItem, stream, mode, { + ADD_WRITE(OFRunLoop_WriteDataQueueItem, stream, mode, { queueItem->_delegate = [delegate retain]; queueItem->_data = [data copy]; }) } + ++ (void)of_addAsyncWriteForStream: (OFStream *) + stream + string: (OFString *)string + encoding: (of_string_encoding_t)encoding + mode: (of_run_loop_mode_t)mode + delegate: (id )delegate +{ + ADD_WRITE(OFRunLoop_WriteStringQueueItem, stream, mode, { + queueItem->_delegate = [delegate retain]; + queueItem->_string = [string copy]; + queueItem->_encoding = encoding; + }) +} + (void)of_addAsyncConnectForTCPSocket: (OFTCPSocket *)stream mode: (of_run_loop_mode_t)mode delegate: (id ) delegate @@ -885,17 +984,31 @@ + (void)of_addAsyncWriteForStream: (OFStream *) stream data: (OFData *)data mode: (of_run_loop_mode_t)mode - block: (of_stream_async_write_block_t)block + block: (of_stream_async_write_data_block_t)block { - ADD_WRITE(OFRunLoop_WriteQueueItem, stream, mode, { + ADD_WRITE(OFRunLoop_WriteDataQueueItem, stream, mode, { queueItem->_data = [data copy]; queueItem->_block = [block copy]; }) } + ++ (void)of_addAsyncWriteForStream: (OFStream *) + stream + string: (OFString *)string + encoding: (of_string_encoding_t)encoding + mode: (of_run_loop_mode_t)mode + block: (of_stream_async_write_string_block_t)block +{ + ADD_WRITE(OFRunLoop_WriteStringQueueItem, stream, mode, { + queueItem->_string = [string copy]; + queueItem->_encoding = encoding; + queueItem->_block = [block copy]; + }) +} + (void)of_addAsyncAcceptForTCPSocket: (OFTCPSocket *)stream mode: (of_run_loop_mode_t)mode block: (of_tcp_socket_async_accept_block_t)block {