Index: src/OFFile.h ================================================================== --- src/OFFile.h +++ src/OFFile.h @@ -104,15 +104,10 @@ * \return An initialized OFFile */ - initWithPath: (OFString*)path andMode: (OFString*)mode; -/** - * \return A boolean whether the end of the file has been reached - */ -- (BOOL)atEndOfFile; - /** * Reads from the file into a buffer. * * \param buf The buffer into which the data is read * \param size The size of the data that should be read. Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -101,11 +101,11 @@ fclose(fp); [super dealloc]; } -- (BOOL)atEndOfFile +- (BOOL)atEndOfStream { if (fp == NULL) return YES; return (feof(fp) == 0 ? NO : YES); Index: src/OFSocket.m ================================================================== --- src/OFSocket.m +++ src/OFSocket.m @@ -47,10 +47,17 @@ sock = INVALID_SOCKET; saddr = NULL; return self; } + +- (BOOL)atEndOfStream +{ + /* FIXME: Implement this! */ + + return NO; +} - (size_t)readNBytes: (size_t)size intoBuffer: (char*)buf { ssize_t ret; Index: src/OFStream.h ================================================================== --- src/OFStream.h +++ src/OFStream.h @@ -19,10 +19,15 @@ { char *cache; size_t cache_len; } +/** + * \return A boolean whether the end of the stream has been reached + */ +- (BOOL)atEndOfStream; + /** * Reads from the stream into a buffer. * * \param buf The buffer into which the data is read * \param size The size of the data that should be read. @@ -36,11 +41,12 @@ * Read until a newline or \0 occurs. * * If you want to use readNBytes afterwards again, you have to clear the cache * before and optionally get the cache before clearing it! * - * \return The line that was read, autoreleased. + * \return The line that was read, autoreleased, or nil if the end of the + * stream has been reached. */ - (OFString*)readLine; /** * Writes from a buffer into the stream. Index: src/OFStream.m ================================================================== --- src/OFStream.m +++ src/OFStream.m @@ -43,10 +43,16 @@ } #endif return self; } + +- (BOOL)atEndOfStream +{ + @throw [OFNotImplementedException newWithClass: isa + andSelector: _cmd]; +} - (size_t)readNBytes: (size_t)size intoBuffer: (char*)buf { @throw [OFNotImplementedException newWithClass: isa @@ -95,10 +101,33 @@ /* Read until we get a newline or \0 */ tmp = [self allocMemoryWithSize: pagesize]; for (;;) { + if ([self atEndOfStream]) { + [self freeMemory: tmp]; + + if (cache == NULL) + return nil; + + ret_c = [self allocMemoryWithSize: cache_len + 1]; + memcpy(ret_c, cache, cache_len); + ret_c[cache_len] = '\0'; + + @try { + ret = [OFString stringWithCString: ret_c]; + } @finally { + [self freeMemory: ret_c]; + } + + [self freeMemory: cache]; + cache = NULL; + cache_len = 0; + + return ret; + } + @try { len = [self readNBytes: pagesize - 1 intoBuffer: tmp]; } @catch (OFException *e) { [self freeMemory: tmp]; @@ -117,11 +146,11 @@ @throw e; } if (cache != NULL) memcpy(ret_c, cache, cache_len); memcpy(ret_c + cache_len, tmp, i); - ret_c[i] = '\0'; + ret_c[cache_len + i] = '\0'; if (i < len) { @try { tmp2 = [self allocMemoryWithSize: len - @@ -141,12 +170,12 @@ if (cache != NULL) [self freeMemory: cache]; cache = NULL; cache_len = 0; } - [self freeMemory: tmp]; + @try { ret = [OFString stringWithCString: ret_c]; } @finally { [self freeMemory: ret_c]; Index: tests/OFHashes/OFHashes.m ================================================================== --- tests/OFHashes/OFHashes.m +++ tests/OFHashes/OFHashes.m @@ -32,11 +32,11 @@ OFMD5Hash *md5 = [OFMD5Hash md5Hash]; OFSHA1Hash *sha1 = [OFSHA1Hash sha1Hash]; OFFile *f = [OFFile fileWithPath: @"testfile" andMode: @"rb"]; - while (![f atEndOfFile]) { + while (![f atEndOfStream]) { len = [f readNBytes: 64 intoBuffer: buf]; [md5 updateWithBuffer: buf ofSize: len]; [sha1 updateWithBuffer: buf