Index: src/OFStream.h ================================================================== --- src/OFStream.h +++ src/OFStream.h @@ -469,10 +469,34 @@ * stream has been reached. */ - (OFString*)readTillDelimiter: (OFString*)delimiter withEncoding: (of_string_encoding_t)encoding; +/** + * \brief Tries to reads until the specified string or \\0 is found or the end + * of stream (see readTillDelimiter:) and returns nil if not enough data + * has been received yet. + * + * \param delimiter The delimiter + * \return The line that was read, autoreleased, or nil if the end of the + * stream has been reached. + */ +- (OFString*)tryReadTillDelimiter: (OFString*)delimiter; + +/** + * \brief Tries to read until the specified string or \\0 is found or the end + * of stream occurs (see readTIllDelimiterWithEncoding:) and returns nil + * if not enough data has been received yet. + * + * \param delimiter The delimiter + * \param encoding The encoding used by the stream + * \return The line that was read, autoreleased, or nil if the end of the + * stream has been reached. + */ +- (OFString*)tryReadTillDelimiter: (OFString*)delimiter + withEncoding: (of_string_encoding_t)encoding; + /** * \brief Returns a boolen whether writes are buffered. * * \return A boolean whether writes are buffered */ Index: src/OFStream.m ================================================================== --- src/OFStream.m +++ src/OFStream.m @@ -561,11 +561,11 @@ return ret; } } } - /* Read until we get a newline or \0 */ + /* Read and see if we get a newline or \0 */ buffer = [self allocMemoryWithSize: of_pagesize]; @try { if ([self _isAtEndOfStream]) { if (cache == NULL) @@ -675,10 +675,29 @@ } - (OFString*)readTillDelimiter: (OFString*)delimiter withEncoding: (of_string_encoding_t)encoding { + OFString *ret = nil; + + while ((ret = [self tryReadTillDelimiter: delimiter + withEncoding: encoding]) == nil) + if ([self isAtEndOfStream]) + return nil; + + return ret; +} + +- (OFString*)tryReadTillDelimiter: (OFString*)delimiter +{ + return [self tryReadTillDelimiter: delimiter + withEncoding: OF_STRING_ENCODING_UTF_8]; +} + +- (OFString*)tryReadTillDelimiter: (OFString*)delimiter + withEncoding: (of_string_encoding_t)encoding +{ const char *delimiterUTF8String; size_t i, j, delimiterLength, bufferLength, retLength; char *retCString, *buffer, *newCache; OFString *ret; @@ -719,105 +738,98 @@ return ret; } } } - /* Read until we get the delimiter or \0 */ + /* Read and see if we get a delimiter or \0 */ buffer = [self allocMemoryWithSize: of_pagesize]; @try { - for (;;) { - if ([self _isAtEndOfStream]) { - if (cache == NULL) - return nil; - - ret = [OFString stringWithCString: cache - encoding: encoding - length: cacheLength]; - - [self freeMemory: cache]; - cache = NULL; - cacheLength = 0; - - return ret; - } - - bufferLength = [self _readNBytes: of_pagesize - intoBuffer: buffer]; - - /* Look if there's the delimiter or \0 */ - for (i = 0; i < bufferLength; i++) { - if (buffer[i] != delimiterUTF8String[j++]) - j = 0; - - if (j == delimiterLength || buffer[i] == '\0') { - if (buffer[i] == '\0') - delimiterLength = 1; - - retLength = cacheLength + i + 1 - - delimiterLength; - retCString = [self - allocMemoryWithSize: retLength]; - - if (cache != NULL && - cacheLength <= retLength) - memcpy(retCString, cache, - cacheLength); - else if (cache != NULL) - memcpy(retCString, cache, - retLength); - if (i >= delimiterLength) - memcpy(retCString + cacheLength, - buffer, i + 1 - - delimiterLength); - - @try { - char *rcs = retCString; - size_t rl = retLength; - - ret = [OFString - stringWithCString: rcs - encoding: encoding - length: rl]; - } @finally { - [self freeMemory: retCString]; - } - - newCache = [self allocMemoryWithSize: - bufferLength - i - 1]; - if (newCache != NULL) - memcpy(newCache, buffer + i + 1, - bufferLength - i - 1); - - [self freeMemory: cache]; - cache = newCache; - cacheLength = bufferLength - i - 1; - - return ret; - } - } - - /* Neither the delimiter nor \0 was found */ - cache = [self resizeMemory: cache - toSize: cacheLength + bufferLength]; - - /* - * It's possible that cacheLen + len is 0 and thus - * cache was set to NULL by resizeMemory:toSize:. - */ - if (cache != NULL) - memcpy(cache + cacheLength, buffer, - bufferLength); - - cacheLength += bufferLength; - } + if ([self _isAtEndOfStream]) { + if (cache == NULL) + return nil; + + ret = [OFString stringWithCString: cache + encoding: encoding + length: cacheLength]; + + [self freeMemory: cache]; + cache = NULL; + cacheLength = 0; + + return ret; + } + + bufferLength = [self _readNBytes: of_pagesize + intoBuffer: buffer]; + + /* Look if there's a delimiter or \0 */ + for (i = 0; i < bufferLength; i++) { + if (buffer[i] != delimiterUTF8String[j++]) + j = 0; + + if (j == delimiterLength || buffer[i] == '\0') { + if (buffer[i] == '\0') + delimiterLength = 1; + + retLength = cacheLength + i + 1 - + delimiterLength; + retCString = [self + allocMemoryWithSize: retLength]; + + if (cache != NULL && cacheLength <= retLength) + memcpy(retCString, cache, cacheLength); + else if (cache != NULL) + memcpy(retCString, cache, retLength); + if (i >= delimiterLength) + memcpy(retCString + cacheLength, + buffer, i + 1 - delimiterLength); + + @try { + char *rcs = retCString; + size_t rl = retLength; + + ret = [OFString + stringWithCString: rcs + encoding: encoding + length: rl]; + } @finally { + [self freeMemory: retCString]; + } + + newCache = [self allocMemoryWithSize: + bufferLength - i - 1]; + if (newCache != NULL) + memcpy(newCache, buffer + i + 1, + bufferLength - i - 1); + + [self freeMemory: cache]; + cache = newCache; + cacheLength = bufferLength - i - 1; + + return ret; + } + } + + /* Neither the delimiter nor \0 was found */ + cache = [self resizeMemory: cache + toSize: cacheLength + bufferLength]; + + /* + * It's possible that cacheLen + len is 0 and thus cache was + * set to NULL by resizeMemory:toSize:. + */ + if (cache != NULL) + memcpy(cache + cacheLength, buffer, + bufferLength); + + cacheLength += bufferLength; } @finally { [self freeMemory: buffer]; } - /* Get rid of a warning, never reached anyway */ - assert(0); + return nil; } - (BOOL)buffersWrites { return buffersWrites;