From 6a7931f87e9df445c037191c0c04773c76550cb2 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Fri, 7 Jun 2019 05:23:44 -0400 Subject: [PATCH] Implementation of index methods --- Source/NSOrderedSet.m | 65 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/Source/NSOrderedSet.m b/Source/NSOrderedSet.m index 04791733c..35f81baa1 100644 --- a/Source/NSOrderedSet.m +++ b/Source/NSOrderedSet.m @@ -227,14 +227,12 @@ static SEL rlSel; - (id) copyWithZone: (NSZone*)zone { NSOrderedSet *copy = [NSOrderedSet_concrete_class allocWithZone: zone]; - return [copy initWithOrderedSet: self copyItems: YES]; } - (id) mutableCopyWithZone: (NSZone*)zone { NSMutableOrderedSet *copy = [NSMutableOrderedSet_concrete_class allocWithZone: zone]; - return [copy initWithOrderedSet: self copyItems: NO]; } @@ -745,18 +743,75 @@ static SEL rlSel; options:(NSEnumerationOptions)opts passingTest:(GSPredicateBlock)predicate { - return 0; + return [[self objectsAtIndexes: indexSet] + indexesOfObjectsWithOptions: opts + passingTest: predicate]; } - (NSUInteger) indexOfObjectPassingTest:(GSPredicateBlock)predicate { - return 0; + return [self indexesOfObjectsWithOptions: 0 passingTest: predicate]; } - (NSUInteger) indexOfObjectWithOptions:(NSEnumerationOptions)opts passingTest:(GSPredicateBlock)predicate { - return 0; + /* TODO: Concurrency. */ + id enumerator = self; + BLOCK_SCOPE BOOL shouldStop = NO; + NSUInteger count = 0; + BLOCK_SCOPE NSUInteger index = NSNotFound; + BLOCK_SCOPE NSLock *indexLock = nil; + + /* If we are enumerating in reverse, use the reverse enumerator for fast + * enumeration. */ + if (opts & NSEnumerationReverse) + { + enumerator = [self reverseObjectEnumerator]; + } + + if (opts & NSEnumerationConcurrent) + { + indexLock = [NSLock new]; + } + { + GS_DISPATCH_CREATE_QUEUE_AND_GROUP_FOR_ENUMERATION(enumQueue, opts) + FOR_IN (id, obj, enumerator) +# if __has_feature(blocks) && (GS_USE_LIBDISPATCH == 1) + dispatch_group_async(enumQueueGroup, enumQueue, ^(void){ + if (shouldStop) + { + return; + } + if (predicate(obj, count, &shouldStop)) + { + // FIXME: atomic operation on the shouldStop variable would be nicer, + // but we don't expose the GSAtomic* primitives anywhere. + [indexLock lock]; + index = count; + // Cancel all other predicate evaluations: + shouldStop = YES; + [indexLock unlock]; + } + }); +# else + if (CALL_BLOCK(predicate, obj, count, &shouldStop)) + { + + index = count; + shouldStop = YES; + } +# endif + if (shouldStop) + { + break; + } + count++; + END_FOR_IN(enumerator) + GS_DISPATCH_TEARDOWN_QUEUE_AND_GROUP_FOR_ENUMERATION(enumQueue, opts); + } + RELEASE(indexLock); + return index; } - (NSIndexSet *) indexesOfObjectsAtIndexes:(NSIndexSet *)indexSet