diff --git a/ChangeLog b/ChangeLog index da9824ab5..2043f5f2d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2003-02-16 Richard Frith-Macdonald + + * Source/GSDictionary.m: ([-isEqualToDictionary:]) implement optimised + version which does not need to create a key enumerator. + * Source/GSArray.m: ditto + * Source/GSSet.m: similar minor optimisations. + 2003-02-15 15:53 Alexander Malmberg * Source/NSRunLoop.m (-performSelector:target:argument:order:modes:): diff --git a/Source/GSArray.m b/Source/GSArray.m index 2281fda5c..d9eeb7a99 100644 --- a/Source/GSArray.m +++ b/Source/GSArray.m @@ -33,6 +33,7 @@ #include static SEL eqSel; +static SEL oaiSel; static Class GSInlineArrayClass; @@ -75,6 +76,7 @@ static Class GSInlineArrayClass; { [self setVersion: 1]; eqSel = @selector(isEqual:); + oaiSel = @selector(objectAtIndex:); GSInlineArrayClass = [GSInlineArray class]; } } @@ -226,6 +228,33 @@ static Class GSInlineArrayClass; return NSNotFound; } +- (BOOL) isEqualToArray: (NSArray*)otherArray +{ + unsigned i; + + if (self == (id)otherArray) + { + return YES; + } + if (_count != [otherArray count]) + { + return NO; + } + if (_count > 0) + { + IMP get1 = [otherArray methodForSelector: oaiSel]; + + for (i = 0; i < _count; i++) + { + if (![_contents_array[i] isEqual: (*get1)(otherArray, oaiSel, i)]) + { + return NO; + } + } + } + return YES; +} + - (id) lastObject { if (_count) diff --git a/Source/GSDictionary.m b/Source/GSDictionary.m index 66fd9868b..1501ade80 100644 --- a/Source/GSDictionary.m +++ b/Source/GSDictionary.m @@ -244,6 +244,42 @@ static SEL objSel; return self; } +- (BOOL) isEqualToDictionary: (NSDictionary*)other +{ + unsigned count; + + if (other == self) + { + return YES; + } + count = map.nodeCount; + if (count == [other count]) + { + if (count > 0) + { + GSIMapEnumerator_t enumerator; + GSIMapNode node; + IMP otherObj = [other methodForSelector: objSel]; + + enumerator = GSIMapEnumeratorForMap(&map); + while ((node = GSIMapEnumeratorNextNode(&enumerator)) != 0) + { + id o1 = node->value.obj; + id o2 = (*otherObj)(other, objSel, node->key.obj); + + if (o1 != o2 && [o1 isEqual: o2] == NO) + { + GSIMapEndEnumerator(&enumerator); + return NO; + } + } + GSIMapEndEnumerator(&enumerator); + } + return YES; + } + return NO; +} + - (NSEnumerator*) keyEnumerator { return AUTORELEASE([[GSDictionaryKeyEnumerator allocWithZone: diff --git a/Source/GSSet.m b/Source/GSSet.m index abea82f8f..25320d300 100644 --- a/Source/GSSet.m +++ b/Source/GSSet.m @@ -39,6 +39,8 @@ #include +static SEL memberSel; + @interface GSSet : NSSet { @public @@ -107,6 +109,7 @@ static Class mutableSetClass; arrayClass = [NSArray class]; setClass = [GSSet class]; mutableSetClass = [GSMutableSet class]; + memberSel = @selector(member:); } } @@ -283,13 +286,19 @@ static Class mutableSetClass; { GSIMapEnumerator_t enumerator; GSIMapNode node; + IMP imp; // -1. members of this set(self) <= that of otherSet if (map.nodeCount > [otherSet count]) { return NO; } + if (map.nodeCount == 0) + { + return YES; + } + imp = [otherSet methodForSelector: memberSel]; enumerator = GSIMapEnumeratorForMap(&map); node = GSIMapEnumeratorNextNode(&enumerator); @@ -297,7 +306,7 @@ static Class mutableSetClass; while (node != 0) { // 1. check the member is in the otherSet. - if ([otherSet member: node->key.obj]) + if ((*imp)(otherSet, memberSel, node->key.obj) != nil) { // 1.1 if true -> continue, try to check the next member. node = GSIMapEnumeratorNextNode(&enumerator); @@ -334,6 +343,10 @@ static Class mutableSetClass; { return NO; } + else if (map.nodeCount == 0) + { + return YES; + } else { GSIMapEnumerator_t enumerator; @@ -360,17 +373,23 @@ static Class mutableSetClass; { return NO; } + else if (map.nodeCount == 0) + { + return YES; + } else { GSIMapEnumerator_t enumerator; GSIMapNode node; + IMP imp; + imp = [other methodForSelector: memberSel]; enumerator = GSIMapEnumeratorForMap(&map); node = GSIMapEnumeratorNextNode(&enumerator); while (node != 0) { - if ([other member: node->key.obj] == nil) + if ((*imp)(other, memberSel, node->key.obj) == nil) { GSIMapEndEnumerator(&enumerator); return NO;