Index: src/OFDictionary.h ================================================================== --- src/OFDictionary.h +++ src/OFDictionary.h @@ -27,11 +27,11 @@ } of_dictionary_list_object_t; /** * The OFDictionary class provides a class for using hash tables. */ -@interface OFDictionary: OFObject +@interface OFDictionary: OFObject { OFList **data; size_t size; } @@ -40,10 +40,18 @@ * * \return A new autoreleased OFDictionary */ + dictionary; +/** + * Creates a new OFDictionary with the specified dictionary. + * + * \param dict An OFDictionary + * \return A new autoreleased OFDictionary + */ ++ dictionaryWithDictionary: (OFDictionary*)dict; + /** * Creates a new OFDictionary with a hash of N bits. * * \param bits The size of the hash to use * \return A new autoreleased OFDictionary @@ -83,10 +91,19 @@ * * \return An initialized OFDictionary */ - init; +/** + * Initializes an already allocated OFDictionary with the specified + * OFDictionary. + * + * \param dict An OFDictionary + * \return An initialized OFDictionary + */ +- initWithDictionary: (OFDictionary*)dict; + /** * Initializes an already allocated OFDictionary with a hash of N bits. * * \param bits The size of the hash to use * \return An initialized OFDictionary Index: src/OFDictionary.m ================================================================== --- src/OFDictionary.m +++ src/OFDictionary.m @@ -13,10 +13,11 @@ #include #import "OFDictionary.h" #import "OFIterator.h" +#import "OFAutoreleasePool.h" #import "OFExceptions.h" /* References for static linking */ void _references_to_categories_of_OFDictionary() { @@ -26,10 +27,15 @@ @implementation OFDictionary + dictionary; { return [[[self alloc] init] autorelease]; } + ++ dictionaryWithDictionary: (OFDictionary*)dict +{ + return [[[self alloc] initWithDictionary: dict] autorelease]; +} + dictionaryWithHashSize: (int)hashsize { return [[[self alloc] initWithHashSize: hashsize] autorelease]; } @@ -79,10 +85,90 @@ [self dealloc]; @throw e; } memset(data, 0, size * sizeof(OFList*)); + return self; +} + +- initWithDictionary: (OFDictionary*)dict +{ + OFAutoreleasePool *pool; + OFIterator *iter; + of_iterator_pair_t pair; + of_iterator_pair_t (*next)(id, SEL); + + self = [super init]; + + if (dict == nil) { + Class c = isa; + size = 0; + [self dealloc]; + @throw [OFInvalidArgumentException newWithClass: c + andSelector: _cmd]; + } + + size = dict->size; + + @try { + data = [self allocMemoryForNItems: size + withSize: sizeof(OFList*)]; + memset(data, 0, size * sizeof(OFList*)); + + pool = [[OFAutoreleasePool alloc] init]; + iter = [dict iterator]; + next = (of_iterator_pair_t(*)(id, SEL)) + [iter methodForSelector: @selector(nextKeyObjectPair)]; + } @catch (OFException *e) { + /* + * We can't use [super dealloc] on OS X here. Compiler bug? + * Anyway, set size to 0 so that [self dealloc] works. + */ + size = 0; + [self dealloc]; + @throw e; + } + + for (;;) { + uint32_t hash; + OFObject *key; + + pair = next(iter, @selector(nextKeyObjectPair)); + + if (pair.key == nil || pair.object == nil) + break; + + hash = pair.hash & (size - 1); + + @try { + key = [pair.key copy]; + } @catch (OFException *e) { + [self dealloc]; + @throw e; + } + + @try { + of_dictionary_list_object_t *o; + + if (data[hash] == nil) + data[hash] = [[OFList alloc] + initWithListObjectSize: + sizeof(of_dictionary_list_object_t)]; + + o = (of_dictionary_list_object_t*) + [data[hash] append: pair.object]; + o->key = key; + o->hash = pair.hash; + } @catch (OFException *e) { + [key release]; + [self dealloc]; + @throw e; + } + } + + [pool release]; + return self; } - initWithHashSize: (int)hashsize { @@ -355,21 +441,22 @@ return iter->object; return nil; } -/* FIXME: Implement this! */ -/* -- (BOOL)isEqual -{ -} - - (id)copy { + return [self retain]; } - (id)mutableCopy +{ + return [[OFMutableDictionary alloc] initWithDictionary: self]; +} + +/* FIXME: Implement this! +- (BOOL)isEqual { } */ - (void)dealloc Index: src/OFIterator.h ================================================================== --- src/OFIterator.h +++ src/OFIterator.h @@ -12,12 +12,13 @@ #import "OFObject.h" #import "OFList.h" #import "OFDictionary.h" typedef struct __of_iterator_pair { - id key; - id object; + id key; + id object; + uint32_t hash; } of_iterator_pair_t; extern int _OFIterator_reference; /** Index: src/OFIterator.m ================================================================== --- src/OFIterator.m +++ src/OFIterator.m @@ -40,23 +40,26 @@ if (last == NULL) { for (; pos < size && data[pos] == nil; pos++); if (pos == size) { next.key = nil; next.object = nil; + next.hash = 0; return next; } last = (of_dictionary_list_object_t*) [data[pos++] first]; next.key = last->key; next.object = last->object; + next.hash = last->hash; return next; } if ((last = last->next) != NULL) { next.key = last->key; next.object = last->object; + next.hash = last->hash; return next; } } } Index: src/OFMutableDictionary.m ================================================================== --- src/OFMutableDictionary.m +++ src/OFMutableDictionary.m @@ -136,16 +136,10 @@ size = newsize; return self; } -/* FIXME: Implement this! */ -/* - (id)copy { + return [[OFDictionary alloc] initWithDictionary: self]; } - -- (id)mutableCopy -{ -} -*/ @end Index: src/OFMutableString.m ================================================================== --- src/OFMutableString.m +++ src/OFMutableString.m @@ -29,15 +29,10 @@ #import "OFMacros.h" #import "asprintf.h" @implementation OFMutableString -- (id)copy -{ - return [[OFString alloc] initWithString: self]; -} - - setToCString: (const char*)str { size_t len; if (string != NULL) @@ -394,6 +389,11 @@ [e dealloc]; } return self; } + +- (id)copy +{ + return [[OFString alloc] initWithString: self]; +} @end Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -266,10 +266,20 @@ - (size_t)length { return length; } + +- (BOOL)isEqual: (id)obj +{ + if (![obj isKindOfClass: [OFString class]]) + return NO; + if (strcmp(string, [obj cString])) + return NO; + + return YES; +} - (id)copy { return [self retain]; } @@ -277,20 +287,10 @@ - (id)mutableCopy { return [[OFMutableString alloc] initWithString: self]; } -- (BOOL)isEqual: (id)obj -{ - if (![obj isKindOfClass: [OFString class]]) - return NO; - if (strcmp(string, [obj cString])) - return NO; - - return YES; -} - - (int)compare: (id)obj { if (![obj isKindOfClass: [OFString class]]) @throw [OFInvalidArgumentException newWithClass: isa andSelector: _cmd]; Index: tests/OFDictionary/OFDictionary.m ================================================================== --- tests/OFDictionary/OFDictionary.m +++ tests/OFDictionary/OFDictionary.m @@ -17,18 +17,19 @@ #import "OFAutoreleasePool.h" #import "OFDictionary.h" #import "OFString.h" #import "OFExceptions.h" -#define TESTS 12 +#define TESTS 15 int main() { int i = 0; OFDictionary *dict = [OFMutableDictionary dictionaryWithHashSize: 16]; + OFDictionary *dict2; OFIterator *iter = [dict iterator]; of_iterator_pair_t pair[2]; OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; OFString *key1 = [OFString stringWithCString: "key1"]; @@ -135,10 +136,38 @@ i++; if (![[dict objectForKey: @"k2"] isEqual: @"o2"]) { printf("\033[K\033[1;31mTest %d/%d failed!\033[m\n", i, TESTS); return 1; } + + i++; + dict2 = [dict copy]; + [dict release]; + if (![[dict2 objectForKey: @"k1"] isEqual: @"o1"] || + ![[dict2 objectForKey: @"k2"] isEqual: @"o2"]) { + printf("\033[K\033[1;31mTest %d/%d failed!\033[m\n", i, TESTS); + return 1; + } + + i++; + dict = [dict2 mutableCopy]; + [dict2 release]; + if (![[dict objectForKey: @"k1"] isEqual: @"o1"] || + ![[dict objectForKey: @"k2"] isEqual: @"o2"]) { + printf("\033[k\033[1;31mtest %d/%d failed!\033[m\n", i, TESTS); + return 1; + } + + i++; + [dict setObject: @"o0" forKey: @"k1"]; + [dict setObject: @"o3" forKey: @"k3"]; + if (![[dict objectForKey: @"k1"] isEqual: @"o0"] || + ![[dict objectForKey: @"k2"] isEqual: @"o2"] || + ![[dict objectForKey: @"k3"] isEqual: @"o3"]) { + printf("\033[k\033[1;31mtest %d/%d failed!\033[m\n", i, TESTS); + return 1; + } printf("\033[1;32mTests successful: %d/%d\033[0m\n", i, TESTS); return 0; }