mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-20 12:16:40 +00:00
Added implementations of some of the new (10.6) NSArray methods that take blocks as arguments. These all use the new GSBlocks.h macros, so compile cleanly with GCC, but can be used by code compiled by clang.
Some of these implementations are not as efficient as they could be (especially the ones that take an NSIndexSet as the first argument). They also don't yet support concurrent enumeration. Apple implements these using Grand Central. We could possibly have a background thread that we send these things to (or use GCD if libdispatch is available). It's not worth spawning a new thread for them, except in exceptional circumstances (and, unfortunately, we can't easily tell how expensive a single iteration of a block is. Possibly we could time one block invocation, and if it's longer than some threshold make it concurrent, but it's probably not worth the effort). git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@29176 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
05f18160df
commit
34c77138fc
4 changed files with 213 additions and 2 deletions
107
Source/NSArray.m
107
Source/NSArray.m
|
@ -1619,19 +1619,122 @@ compare(id elem1, id elem2, void* context)
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void)enumerateObjectsUsingBlock: (GSEnumeratorBlock)aBlock
|
||||
{
|
||||
[self enumerateObjectsWithOptions: 0 usingBlock: aBlock];
|
||||
}
|
||||
- (void)enumerateObjectsWithOptions: (NSEnumerationOptions)opts
|
||||
usingBlock: (GSEnumeratorBlock)aBlock
|
||||
{
|
||||
NSUInteger count = 0;
|
||||
BOOL shouldStop = NO;
|
||||
FOR_IN (id, obj, self)
|
||||
id<NSFastEnumeration> enumerator = self;
|
||||
|
||||
/* If we are enumerating in reverse, use the reverse enumerator for fast
|
||||
* enumeration. */
|
||||
if (opts & NSEnumerationReverse)
|
||||
{
|
||||
enumerator = [self reverseObjectEnumerator];
|
||||
}
|
||||
|
||||
FOR_IN (id, obj, enumerator)
|
||||
CALL_BLOCK(aBlock, obj, count++, &shouldStop);
|
||||
if (shouldStop)
|
||||
{
|
||||
return;
|
||||
}
|
||||
END_FOR_IN(self)
|
||||
END_FOR_IN(enumerator)
|
||||
}
|
||||
- (void)enumerateObjectsAtIndexes: (NSIndexSet*)indexSet
|
||||
options: (NSEnumerationOptions)opts
|
||||
usingBlock: (GSEnumeratorBlock)block
|
||||
{
|
||||
[[self objectsAtIndexes: indexSet] enumerateObjectsWithOptions: opts
|
||||
usingBlock: block];
|
||||
}
|
||||
|
||||
- (NSIndexSet *)indexesOfObjectsWithOptions: (NSEnumerationOptions)opts
|
||||
passingTest: (GSPredicateBlock)predicate
|
||||
{
|
||||
/* TODO: Concurrency. */
|
||||
NSMutableIndexSet *set = [NSMutableIndexSet indexSet];
|
||||
BOOL shouldStop = NO;
|
||||
id<NSFastEnumeration> enumerator = self;
|
||||
NSUInteger count = 0;
|
||||
|
||||
/* If we are enumerating in reverse, use the reverse enumerator for fast
|
||||
* enumeration. */
|
||||
if (opts & NSEnumerationReverse)
|
||||
{
|
||||
enumerator = [self reverseObjectEnumerator];
|
||||
}
|
||||
|
||||
FOR_IN (id, obj, self)
|
||||
if (CALL_BLOCK(predicate, obj, count, &shouldStop))
|
||||
{
|
||||
/* TODO: It would be more efficient to collect an NSRange and only
|
||||
* pass it to the index set when CALL_BLOCK returned NO. */
|
||||
[set addIndex: count];
|
||||
}
|
||||
if (shouldStop)
|
||||
{
|
||||
return set;
|
||||
}
|
||||
count++;
|
||||
END_FOR_IN(self)
|
||||
return set;
|
||||
}
|
||||
- (NSIndexSet*)indexesOfObjectsPassingTest: (GSPredicateBlock)predicate
|
||||
{
|
||||
return [self indexesOfObjectsWithOptions: 0 passingTest: predicate];
|
||||
}
|
||||
- (NSIndexSet*)indexesOfObjectsAtIndexes: (NSIndexSet*)indexSet
|
||||
options: (NSEnumerationOptions)opts
|
||||
passingTest: (GSPredicateBlock)predicate
|
||||
{
|
||||
return [[self objectsAtIndexes: indexSet] indexesOfObjectsWithOptions: opts
|
||||
passingTest: predicate];
|
||||
}
|
||||
- (NSUInteger)indexOfObjectWithOptions: (NSEnumerationOptions)opts
|
||||
passingTest: (GSPredicateBlock)predicate
|
||||
{
|
||||
/* TODO: Concurrency. */
|
||||
id<NSFastEnumeration> enumerator = self;
|
||||
BOOL shouldStop = NO;
|
||||
NSUInteger count = 0;
|
||||
|
||||
/* If we are enumerating in reverse, use the reverse enumerator for fast
|
||||
* enumeration. */
|
||||
if (opts & NSEnumerationReverse)
|
||||
{
|
||||
enumerator = [self reverseObjectEnumerator];
|
||||
}
|
||||
|
||||
FOR_IN (id, obj, self)
|
||||
if (CALL_BLOCK(predicate, obj, count, &shouldStop))
|
||||
{
|
||||
return count;
|
||||
}
|
||||
if (shouldStop)
|
||||
{
|
||||
return NSNotFound;
|
||||
}
|
||||
count++;
|
||||
END_FOR_IN(self)
|
||||
return NSNotFound;
|
||||
}
|
||||
- (NSUInteger)indexOfObjectPassingTest: (GSPredicateBlock)predicate
|
||||
{
|
||||
return [self indexOfObjectWithOptions: 0 passingTest: predicate];
|
||||
}
|
||||
- (NSUInteger)indexOfObjectAtIndexes: (NSIndexSet*)indexSet
|
||||
options: (NSEnumerationOptions)opts
|
||||
passingTest: (GSPredicateBlock)predicate
|
||||
{
|
||||
return [[self objectsAtIndexes: indexSet] indexOfObjectWithOptions: 0
|
||||
passingTest: predicate];
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue