Optimise test for dictionary equality

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@15973 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2003-02-16 11:31:28 +00:00
parent 46b480c41d
commit 6da6e5b251
4 changed files with 93 additions and 2 deletions

View file

@ -1,3 +1,10 @@
2003-02-16 Richard Frith-Macdonald <rfm@gnu.org>
* 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 <alexander@malmberg.org> 2003-02-15 15:53 Alexander Malmberg <alexander@malmberg.org>
* Source/NSRunLoop.m (-performSelector:target:argument:order:modes:): * Source/NSRunLoop.m (-performSelector:target:argument:order:modes:):

View file

@ -33,6 +33,7 @@
#include <Foundation/NSDebug.h> #include <Foundation/NSDebug.h>
static SEL eqSel; static SEL eqSel;
static SEL oaiSel;
static Class GSInlineArrayClass; static Class GSInlineArrayClass;
@ -75,6 +76,7 @@ static Class GSInlineArrayClass;
{ {
[self setVersion: 1]; [self setVersion: 1];
eqSel = @selector(isEqual:); eqSel = @selector(isEqual:);
oaiSel = @selector(objectAtIndex:);
GSInlineArrayClass = [GSInlineArray class]; GSInlineArrayClass = [GSInlineArray class];
} }
} }
@ -226,6 +228,33 @@ static Class GSInlineArrayClass;
return NSNotFound; 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 - (id) lastObject
{ {
if (_count) if (_count)

View file

@ -244,6 +244,42 @@ static SEL objSel;
return self; 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 - (NSEnumerator*) keyEnumerator
{ {
return AUTORELEASE([[GSDictionaryKeyEnumerator allocWithZone: return AUTORELEASE([[GSDictionaryKeyEnumerator allocWithZone:

View file

@ -39,6 +39,8 @@
#include <base/GSIMap.h> #include <base/GSIMap.h>
static SEL memberSel;
@interface GSSet : NSSet @interface GSSet : NSSet
{ {
@public @public
@ -107,6 +109,7 @@ static Class mutableSetClass;
arrayClass = [NSArray class]; arrayClass = [NSArray class];
setClass = [GSSet class]; setClass = [GSSet class];
mutableSetClass = [GSMutableSet class]; mutableSetClass = [GSMutableSet class];
memberSel = @selector(member:);
} }
} }
@ -283,13 +286,19 @@ static Class mutableSetClass;
{ {
GSIMapEnumerator_t enumerator; GSIMapEnumerator_t enumerator;
GSIMapNode node; GSIMapNode node;
IMP imp;
// -1. members of this set(self) <= that of otherSet // -1. members of this set(self) <= that of otherSet
if (map.nodeCount > [otherSet count]) if (map.nodeCount > [otherSet count])
{ {
return NO; return NO;
} }
if (map.nodeCount == 0)
{
return YES;
}
imp = [otherSet methodForSelector: memberSel];
enumerator = GSIMapEnumeratorForMap(&map); enumerator = GSIMapEnumeratorForMap(&map);
node = GSIMapEnumeratorNextNode(&enumerator); node = GSIMapEnumeratorNextNode(&enumerator);
@ -297,7 +306,7 @@ static Class mutableSetClass;
while (node != 0) while (node != 0)
{ {
// 1. check the member is in the otherSet. // 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. // 1.1 if true -> continue, try to check the next member.
node = GSIMapEnumeratorNextNode(&enumerator); node = GSIMapEnumeratorNextNode(&enumerator);
@ -334,6 +343,10 @@ static Class mutableSetClass;
{ {
return NO; return NO;
} }
else if (map.nodeCount == 0)
{
return YES;
}
else else
{ {
GSIMapEnumerator_t enumerator; GSIMapEnumerator_t enumerator;
@ -360,17 +373,23 @@ static Class mutableSetClass;
{ {
return NO; return NO;
} }
else if (map.nodeCount == 0)
{
return YES;
}
else else
{ {
GSIMapEnumerator_t enumerator; GSIMapEnumerator_t enumerator;
GSIMapNode node; GSIMapNode node;
IMP imp;
imp = [other methodForSelector: memberSel];
enumerator = GSIMapEnumeratorForMap(&map); enumerator = GSIMapEnumeratorForMap(&map);
node = GSIMapEnumeratorNextNode(&enumerator); node = GSIMapEnumeratorNextNode(&enumerator);
while (node != 0) while (node != 0)
{ {
if ([other member: node->key.obj] == nil) if ((*imp)(other, memberSel, node->key.obj) == nil)
{ {
GSIMapEndEnumerator(&enumerator); GSIMapEndEnumerator(&enumerator);
return NO; return NO;