@@ -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