Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -7,12 +7,13 @@ SRCS = OFArray.m \ OFAutoreleasePool.m \ OFConstString.m \ OFDictionary.m \ OFExceptions.m \ - OFHashes.m \ OFFile.m \ + OFHashes.m \ + OFIterator.m \ OFList.m \ OFNumber.m \ OFObject.m \ ${OFPLUGIN_M} \ OFString.m \ ADDED src/OFIterator.h Index: src/OFIterator.h ================================================================== --- src/OFIterator.h +++ src/OFIterator.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2008 - 2009 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of libobjfw. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE included in + * the packaging of this file. + */ + +#import "OFObject.h" +#import "OFList.h" +#import "OFDictionary.h" + +/** + * The OFIterator class provides methods to iterate through objects. + */ +@interface OFIterator: OFObject +{ + OFList **data; + size_t size; + size_t pos; + of_list_object_t *last; +} + +- initWithData: (OFList**)data + andSize: (size_t)size; + +/** + * Returns the next object in the dictionary. + * + * Always call it twice in a row, as it returns the key on the first call and + * the value on the second. Therefore, if you want a key value pair, you have + * to call: + * + * key = [iter nextObject];\n + * value = [iter nextObject]; + * + * When there is no more object left, an OFNotInSetException is thrown. + * + * \return The key on the first call and the value on the second + */ +- (id)nextObject; + +/** + * Resets the iterator, so the next call to nextObject returns the first again. + */ +- reset; +@end + +@interface OFDictionary (OFIterator) +/** + * \return An OFIterator for the OFDictionary + */ +- (OFIterator*)getIterator; +@end ADDED src/OFIterator.m Index: src/OFIterator.m ================================================================== --- src/OFIterator.m +++ src/OFIterator.m @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2008 - 2009 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of libobjfw. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE included in + * the packaging of this file. + */ + +#import + +#import "OFIterator.h" +#import "OFDictionary.h" +#import "OFExceptions.h" + +@implementation OFIterator +- initWithData: (OFList**)data_ + andSize: (size_t)size_ +{ + self = [super init]; + + data = data_; + size = size_; + + pos = 0; + last = NULL; + + return self; +} + +- (id)nextObject +{ + if (last == NULL) { + for (; pos < size && data[pos] == nil; pos++); + if (pos == size) + @throw [OFNotInSetException + newWithClass: [OFDictionary class]]; + + return (last = [data[pos++] first])->object; + } + + if ((last = last->next) != NULL) + return last->object; + + return [self nextObject]; +} + +- reset +{ + pos = 0; + last = NULL; + + return self; +} +@end + +@implementation OFDictionary (OFIterator) +- (OFIterator*)getIterator +{ + return [[[OFIterator alloc] initWithData: data + andSize: size] autorelease]; +} +@end Index: tests/OFDictionary/OFDictionary.m ================================================================== --- tests/OFDictionary/OFDictionary.m +++ tests/OFDictionary/OFDictionary.m @@ -14,10 +14,11 @@ #include #include #import "OFAutoreleasePool.h" #import "OFDictionary.h" +#import "OFIterator.h" #import "OFConstString.h" #import "OFString.h" #import "OFExceptions.h" int @@ -24,10 +25,11 @@ main() { BOOL caught; OFDictionary *dict = [OFDictionary dictionaryWithHashSize: 16]; + OFIterator *iter = [dict getIterator]; OFAutoreleasePool *pool = [OFAutoreleasePool new]; OFString *key1 = [OFString stringWithCString: "key1"]; OFString *key2 = [OFString stringWithCString: "key2"]; OFString *value1 = [OFString stringWithCString: "value1"]; @@ -38,16 +40,35 @@ [dict set: key2 to: value2]; [pool release]; if (strcmp([[dict get: @"key1"] cString], "value1")) { - puts("\033[K\033[1;31mTest 1/4 failed!\033[m"); + puts("\033[K\033[1;31mTest 1/6 failed!\033[m"); return 1; } if (strcmp([[dict get: key2] cString], "value2")) { - puts("\033[K\033[1;31mTest 2/4 failed!\033[m"); + puts("\033[K\033[1;31mTest 2/6 failed!\033[m"); + return 1; + } + + if (![[iter nextObject] isEqual: @"key2"] || + ![[iter nextObject] isEqual: @"value2"] || + ![[iter nextObject] isEqual: @"key1"] || + ![[iter nextObject] isEqual: @"value1"]) { + puts("\033[K\033[1;31mTest 3/6 failed!\033[m"); + return 1; + } + + caught = NO; + @try { + [iter nextObject]; + } @catch (OFNotInSetException *e) { + caught = YES; + } + if (!caught) { + puts("\033[K\033[1;31mTest 4/6 failed!\033[m"); return 1; } caught = NO; @try { @@ -54,11 +75,11 @@ [dict get: @"key3"]; } @catch (OFNotInSetException *e) { caught = YES; } if (!caught) { - puts("\033[K\033[1;31mTest 3/4 failed!\033[m"); + puts("\033[K\033[1;31mTest 5/6 failed!\033[m"); return 1; } [dict remove: @"key2"]; caught = NO; @@ -66,12 +87,13 @@ [dict remove: @"key2"]; } @catch (OFNotInSetException *e) { caught = YES; } if (!caught) { - puts("\033[K\033[1;31mTest 4/4 failed!\033[m"); + puts("\033[K\033[1;31mTest 6/6 failed!\033[m"); return 1; } - puts("\033[1;32mTests successful: 4/4\033[0m"); + puts("\033[1;32mTests successful: 6/6\033[0m"); + return 0; }