mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 00:41:02 +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
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
2009-12-27 David Chisnall <theraven@gna.org>
|
||||
|
||||
* Source/NSArray.m
|
||||
* Headers/Foundation/NSArray.h
|
||||
Added some block method implementations.
|
||||
|
||||
* Headers/Foundation/NSObjCRuntime.h
|
||||
Added constants for enumeration.
|
||||
|
||||
|
||||
2009-12-27 David Chisnall <theraven@gna.org>
|
||||
|
||||
* Source/GSFastEnumeration.h: Added macros implementing for..in loops.
|
||||
|
|
|
@ -117,6 +117,7 @@ extern "C" {
|
|||
- (id) valueForKey: (NSString*)key;
|
||||
#endif
|
||||
DEFINE_BLOCK_TYPE(GSEnumeratorBlock, void, id, NSUInteger, BOOL*);
|
||||
DEFINE_BLOCK_TYPE(GSPredicateBlock, BOOL, id, NSUInteger, BOOL*);
|
||||
/**
|
||||
* Enumerate over the collection using the given block. The first argument is
|
||||
* the object and the second is the index in the array. The final argument is
|
||||
|
@ -124,6 +125,84 @@ DEFINE_BLOCK_TYPE(GSEnumeratorBlock, void, id, NSUInteger, BOOL*);
|
|||
* this to YES will interrupt the enumeration.
|
||||
*/
|
||||
- (void)enumerateObjectsUsingBlock: (GSEnumeratorBlock)aBlock;
|
||||
/**
|
||||
* Enumerate over the collection using the given block. The first argument is
|
||||
* the object and the second is the index in the array. The final argument is
|
||||
* a pointer to a BOOL indicating whether the enumeration should stop. Setting
|
||||
* this to YES will interrupt the enumeration.
|
||||
*
|
||||
* The opts argument is a bitfield. Setting the NSNSEnumerationConcurrent flag
|
||||
* specifies that it is thread-safe. The NSEnumerationReverse bit specifies
|
||||
* that it should be enumerated in reverse order.
|
||||
*/
|
||||
- (void)enumerateObjectsWithOptions: (NSEnumerationOptions)opts
|
||||
usingBlock: (GSEnumeratorBlock)aBlock;
|
||||
/**
|
||||
* Enumerate over the specified indexes in the collection using the given
|
||||
* block. The first argument is the object and the second is the index in the
|
||||
* array. The final argument is a pointer to a BOOL indicating whether the
|
||||
* enumeration should stop. Setting this to YES will interrupt the
|
||||
* enumeration.
|
||||
*
|
||||
* The opts argument is a bitfield. Setting the NSNSEnumerationConcurrent flag
|
||||
* specifies that it is thread-safe. The NSEnumerationReverse bit specifies
|
||||
* that it should be enumerated in reverse order.
|
||||
*/
|
||||
- (void)enumerateObjectsAtIndexes: (NSIndexSet*)indexSet
|
||||
options: (NSEnumerationOptions)opts
|
||||
usingBlock: (GSEnumeratorBlock)block;
|
||||
/**
|
||||
* Returns the indexes of the objects in a collection that match the condition
|
||||
* specified by the block.
|
||||
*
|
||||
* The opts argument is a bitfield. Setting the NSNSEnumerationConcurrent flag
|
||||
* specifies that it is thread-safe. The NSEnumerationReverse bit specifies
|
||||
* that it should be enumerated in reverse order.
|
||||
*/
|
||||
- (NSIndexSet *)indexesOfObjectsWithOptions: (NSEnumerationOptions)opts
|
||||
passingTest: (GSPredicateBlock)predicate;
|
||||
/**
|
||||
* Returns the indexes of the objects in a collection that match the condition
|
||||
* specified by the block.
|
||||
*/
|
||||
- (NSIndexSet*)indexesOfObjectsPassingTest: (GSPredicateBlock)predicate;
|
||||
/**
|
||||
* Returns the indexes of the objects in a collection that match the condition
|
||||
* specified by the block and are in the range specified by the index set.
|
||||
*
|
||||
* The opts argument is a bitfield. Setting the NSNSEnumerationConcurrent flag
|
||||
* specifies that it is thread-safe. The NSEnumerationReverse bit specifies
|
||||
* that it should be enumerated in reverse order.
|
||||
*/
|
||||
- (NSIndexSet*)indexesOfObjectsAtIndexes: (NSIndexSet*)indexSet
|
||||
options: (NSEnumerationOptions)opts
|
||||
passingTest: (GSPredicateBlock)predicate;
|
||||
/**
|
||||
* Returns the index of the first object in the array that matches the
|
||||
* condition specified by the block.
|
||||
*
|
||||
* The opts argument is a bitfield. Setting the NSNSEnumerationConcurrent flag
|
||||
* specifies that it is thread-safe. The NSEnumerationReverse bit specifies
|
||||
* that it should be enumerated in reverse order.
|
||||
*/
|
||||
- (NSUInteger)indexOfObjectWithOptions: (NSEnumerationOptions)opts
|
||||
passingTest: (GSPredicateBlock)predicate;
|
||||
/**
|
||||
* Returns the index of the first object in the array that matches the
|
||||
* condition specified by the block.
|
||||
*/
|
||||
- (NSUInteger)indexOfObjectPassingTest: (GSPredicateBlock)predicate;
|
||||
/**
|
||||
* Returns the index of the first object in the specified range in a collection
|
||||
* that matches the condition specified by the block.
|
||||
*
|
||||
* The opts argument is a bitfield. Setting the NSNSEnumerationConcurrent flag
|
||||
* specifies that it is thread-safe. The NSEnumerationReverse bit specifies
|
||||
* that it should be enumerated in reverse order.
|
||||
*/
|
||||
- (NSUInteger)indexOfObjectAtIndexes: (NSIndexSet*)indexSet
|
||||
options: (NSEnumerationOptions)opts
|
||||
passingTest: (GSPredicateBlock)predicate;
|
||||
@end
|
||||
|
||||
|
||||
|
|
|
@ -67,6 +67,25 @@ typedef float CGFloat;
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
/**
|
||||
* Specifies that the enumeration is concurrency-safe. Note that this does
|
||||
* not mean that it will be carried out in a concurrent manner, only that
|
||||
* it can be.
|
||||
*/
|
||||
NSEnumerationConcurrent = (1UL << 0),
|
||||
/**
|
||||
* Specifies that the enumeration should happen in the opposite of the
|
||||
* natural order of the collection.
|
||||
*/
|
||||
NSEnumerationReverse = (1UL << 1)
|
||||
};
|
||||
|
||||
/** Bitfield used to specify options to control enumeration over collections.
|
||||
*/
|
||||
typedef NSUInteger NSEnumerationOptions;
|
||||
|
||||
#if OS_API_VERSION(100500,GS_API_LATEST)
|
||||
GS_EXPORT NSString *NSStringFromProtocol(Protocol *aProtocol);
|
||||
GS_EXPORT Protocol *NSProtocolFromString(NSString *aProtocolName);
|
||||
|
|
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…
Reference in a new issue