Merge pull request #46 from gnustep/add_nsorderedset_classcluster

Add nsorderedset classcluster
This commit is contained in:
Gregory Casamento 2019-07-02 12:46:20 -04:00 committed by GitHub
commit 75f3f0b57d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 2889 additions and 18 deletions

View file

@ -95,6 +95,7 @@
#import <Foundation/NSNull.h>
#import <Foundation/NSNumberFormatter.h>
#import <Foundation/NSOperation.h>
#import <Foundation/NSOrderedSet.h>
#import <Foundation/NSPathUtilities.h>
#import <Foundation/NSPointerArray.h>
#import <Foundation/NSPointerFunctions.h>

View file

@ -107,6 +107,8 @@ DEFINE_BLOCK_TYPE(GSKeysAndObjectsPredicateBlock, BOOL, GS_GENERIC_TYPE_F(KeyT,i
#endif
- (GS_GENERIC_CLASS(NSArray,ValT)*) keysSortedByValueUsingSelector: (SEL)comp;
- (GS_GENERIC_CLASS(NSArray,ValT)*) keysSortedByValueUsingComparator:(NSComparator)cmptr;
- (GS_GENERIC_CLASS(NSArray,ValT)*) keysSortedByValueWithOptions:(NSSortOptions)opts usingComparator:(NSComparator)cmptr;
- (GS_GENERIC_CLASS(NSEnumerator,ValT)*) objectEnumerator; // Primitive
- (GS_GENERIC_TYPE(ValT)) objectForKey:
(GS_GENERIC_TYPE(KeyT))aKey; // Primitive

View file

@ -0,0 +1,213 @@
/** Interface for NSOrderedSet, NSMutableOrderedSet for GNUStep
Copyright (C) 2019 Free Software Foundation, Inc.
Written by: Gregory John Casamento <greg.casamento@gmail.com>
Created: May 17 2019
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02111 USA.
*/
#ifndef _NSOrderedSet_h_GNUSTEP_BASE_INCLUDE
#define _NSOrderedSet_h_GNUSTEP_BASE_INCLUDE
#if OS_API_VERSION(MAC_OS_X_VERSION_10_7,GS_API_LATEST)
#import <GNUstepBase/GSVersionMacros.h>
#import <GNUstepBase/GSBlocks.h>
#import <Foundation/NSObject.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSIndexSet.h>
#import <Foundation/NSKeyedArchiver.h>
#if defined(__cplusplus)
extern "C" {
#endif
@class GS_GENERIC_CLASS(NSArray, ElementT);
@class GS_GENERIC_CLASS(NSEnumerator, ElementT);
@class GS_GENERIC_CLASS(NSSet, ElementT);
@class GS_GENERIC_CLASS(NSDictionary, KeyT:id<NSCopying>, ValT);
@class NSString;
@class NSPredicate;
@interface GS_GENERIC_CLASS(NSOrderedSet, __covariant ElementT) : NSObject <NSCoding,
NSCopying,
NSMutableCopying,
NSFastEnumeration>
// class methods
+ (instancetype) orderedSet;
+ (instancetype) orderedSetWithArray:(GS_GENERIC_CLASS(NSArray, ElementT)*)objects;
+ (instancetype) orderedSetWithArray:(GS_GENERIC_CLASS(NSArray, ElementT)*)objects
range: (NSRange)range
copyItems:(BOOL)flag;
+ (instancetype) orderedSetWithObject:(GS_GENERIC_TYPE(ElementT))anObject;
+ (instancetype) orderedSetWithObjects:(GS_GENERIC_TYPE(ElementT))firstObject, ...;
+ (instancetype) orderedSetWithObjects:(const GS_GENERIC_TYPE(ElementT)[])objects
count:(NSUInteger) count;
+ (instancetype) orderedSetWithOrderedSet:(GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet;
+ (instancetype) orderedSetWithSet:(GS_GENERIC_CLASS(NSSet, ElementT)*)aSet;
+ (instancetype) orderedSetWithSet:(GS_GENERIC_CLASS(NSSet, ElementT)*)aSet
copyItems:(BOOL)flag;
// instance methods
- (instancetype) initWithArray:(GS_GENERIC_CLASS(NSArray, ElementT)*)array;
- (instancetype) initWithArray:(GS_GENERIC_CLASS(NSArray, ElementT)*)array copyItems:(BOOL)flag;
- (instancetype) initWithArray:(GS_GENERIC_CLASS(NSArray, ElementT)*)array
range:(NSRange)range
copyItems:(BOOL)flag;
- (instancetype) initWithObject:(id)object;
- (instancetype) initWithObjects:(GS_GENERIC_TYPE(ElementT))firstObject, ...;
- (instancetype) initWithObjects:(const GS_GENERIC_TYPE(ElementT)[])objects
count:(NSUInteger)count;
- (instancetype) initWithOrderedSet:(GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet;
- (instancetype) initWithOrderedSet:(GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet
copyItems:(BOOL)flag;
- (instancetype) initWithOrderedSet:(GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet
range: (NSRange)range
copyItems:(BOOL)flag;
- (instancetype) initWithSet:(GS_GENERIC_CLASS(NSSet, ElementT)*)aSet;
- (instancetype) initWithSet:(GS_GENERIC_CLASS(NSSet, ElementT)*)aSet copyItems:(BOOL)flag;
- (instancetype) init;
- (NSUInteger) count;
- (BOOL)containsObject:(GS_GENERIC_TYPE(ElementT))anObject;
- (void) enumerateObjectsAtIndexes:(NSIndexSet *)indexSet
options:(NSEnumerationOptions)opts
usingBlock:(GSEnumeratorBlock)aBlock;
- (void) enumerateObjectsUsingBlock: (GSEnumeratorBlock)aBlock;
- (void) enumerateObjectsWithOptions:(NSEnumerationOptions)opts
usingBlock:(GSEnumeratorBlock)aBlock;
- (GS_GENERIC_TYPE(ElementT)) firstObject;
- (GS_GENERIC_TYPE(ElementT)) lastObject;
- (GS_GENERIC_TYPE(ElementT)) objectAtIndex: (NSUInteger)index;
- (GS_GENERIC_TYPE(ElementT)) objectAtIndexedSubscript:(NSUInteger)index;
- (GS_GENERIC_CLASS(NSArray, ElementT)*) objectsAtIndexes:(NSIndexSet *)indexes;
- (NSUInteger) indexOfObject:(GS_GENERIC_TYPE(ElementT))objects;
- (NSUInteger) indexOfObject: (id)key
inSortedRange: (NSRange)range
options: (NSBinarySearchingOptions)options
usingComparator: (NSComparator)comparator;
- (NSUInteger) indexOfObjectAtIndexes:(NSIndexSet *)indexSet
options:(NSEnumerationOptions)opts
passingTest:(GSPredicateBlock)predicate;
- (NSUInteger) indexOfObjectPassingTest:(GSPredicateBlock)predicate;
- (NSUInteger) indexOfObjectWithOptions:(NSEnumerationOptions)opts
passingTest:(GSPredicateBlock)predicate;
- (NSIndexSet *) indexesOfObjectsAtIndexes:(NSIndexSet *)indexSet
options:(NSEnumerationOptions)opts
passingTest:(GSPredicateBlock)predicate;
- (NSIndexSet *)indexesOfObjectsPassingTest:(GSPredicateBlock)predicate;
- (NSIndexSet *) indexesOfObjectsWithOptions:(NSEnumerationOptions)opts
passingTest:(GSPredicateBlock)predicate;
- (GS_GENERIC_CLASS(NSEnumerator, ElementT)*) objectEnumerator;
- (GS_GENERIC_CLASS(NSEnumerator, ElementT)*) reverseObjectEnumerator;
- (NSOrderedSet *)reversedOrderedSet;
- (void) getObjects: (__unsafe_unretained GS_GENERIC_TYPE(ElementT)[])aBuffer
range: (NSRange)aRange;
// Key value coding support
- (void) setValue: (GS_GENERIC_TYPE(ElementT))value forKey: (NSString*)key;
- (GS_GENERIC_TYPE(ElementT)) valueForKey: (NSString*)key;
// Comparing Sets
- (BOOL) isEqualToOrderedSet: (NSOrderedSet *)aSet;
// Set operations
- (BOOL) intersectsOrderedSet: (NSOrderedSet *)aSet;
- (BOOL) intersectsSet: (NSSet *)aSet;
- (BOOL) isSubsetOfOrderedSet: (NSOrderedSet *)aSet;
- (BOOL) isSubsetOfSet:(NSSet *)aSet;
// Creating a Sorted Array
- (GS_GENERIC_CLASS(NSArray, ElementT) *) sortedArrayUsingDescriptors:(NSArray *)sortDescriptors;
- (GS_GENERIC_CLASS(NSArray, ElementT) *) sortedArrayUsingComparator:
(NSComparator)comparator;
- (GS_GENERIC_CLASS(NSArray, ElementT) *)
sortedArrayWithOptions: (NSSortOptions)options
usingComparator: (NSComparator)comparator;
// Filtering Ordered Sets
- (NSOrderedSet *)filteredOrderedSetUsingPredicate: (NSPredicate *)predicate;
// Describing a set
- (NSString *) description;
- (NSString *) descriptionWithLocale: (NSLocale *)locale;
- (NSString *) descriptionWithLocale: (NSLocale *)locale indent: (BOOL)flag;
// Convert to other types
- (NSArray *) array;
- (NSSet *) set;
@end
// Mutable Ordered Set
@interface GS_GENERIC_CLASS(NSMutableOrderedSet, __covariant ElementT) : NSOrderedSet
// Creating a Mutable Ordered Set
+ (instancetype)orderedSetWithCapacity: (NSUInteger)capacity;
- (instancetype)initWithCapacity: (NSUInteger)capacity;
- (instancetype) init;
- (void)addObject:(GS_GENERIC_TYPE(ElementT))anObject;
- (void)addObjects:(const GS_GENERIC_TYPE(ElementT)[])objects count:(NSUInteger)count;
- (void)addObjectsFromArray:(GS_GENERIC_CLASS(NSArray, ElementT)*)otherArray;
- (void)insertObject:(GS_GENERIC_TYPE(ElementT))object atIndex:(NSUInteger)index;
- (void)setObject:(GS_GENERIC_TYPE(ElementT))object atIndexedSubscript:(NSUInteger)index;
- (void)insertObjects:(GS_GENERIC_CLASS(NSArray, ElementT)*)array atIndexes:(NSIndexSet *)indexes;
- (void)removeObject:(GS_GENERIC_TYPE(ElementT))object;
- (void)removeObjectAtIndex:(NSUInteger)index;
- (void)removeObjectsAtIndexes:(NSIndexSet *)indexes;
- (void)removeObjectsInArray:(GS_GENERIC_CLASS(NSArray, ElementT)*)otherArray;
- (void)removeObjectsInRange:(NSRange)range;
- (void)removeAllObjects;
- (void)replaceObjectAtIndex:(NSUInteger)index
withObject:(GS_GENERIC_TYPE(ElementT))object;
- (void) replaceObjectsAtIndexes: (NSIndexSet *)indexes
withObjects: (GS_GENERIC_CLASS(NSArray, ElementT)*)objects;
- (void) replaceObjectsInRange:(NSRange)range
withObjects:(const GS_GENERIC_TYPE(ElementT)[])objects
count: (NSUInteger)count;
- (void)setObject:(GS_GENERIC_TYPE(ElementT))object atIndex:(NSUInteger)index;
- (void)moveObjectsAtIndexes:(NSIndexSet *)indexes toIndex:(NSUInteger)index;
- (void) exchangeObjectAtIndex:(NSUInteger)index withObjectAtIndex:(NSUInteger)otherIndex;
- (void)filterUsingPredicate:(NSPredicate *)predicate;
- (void) sortUsingDescriptors:(NSArray *)descriptors;
- (void) sortUsingComparator: (NSComparator)comparator;
- (void) sortWithOptions: (NSSortOptions)options
usingComparator: (NSComparator)comparator;
- (void) sortRange: (NSRange)range
options:(NSSortOptions)options
usingComparator: (NSComparator)comparator;
- (void) intersectOrderedSet:(GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet;
- (void) intersectSet:(GS_GENERIC_CLASS(NSSet, ElementT)*)aSet;
- (void) minusOrderedSet:(GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet;
- (void) minusSet:(GS_GENERIC_CLASS(NSSet, ElementT)*)aSet;
- (void) unionOrderedSet:(GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet;
- (void) unionSet:(GS_GENERIC_CLASS(NSSet, ElementT)*)aSet;
- (instancetype) initWithCoder: (NSCoder *)coder;
@end
#if defined(__cplusplus)
}
#endif
#endif /* OS_API_VERSION check */
#endif /* _NSOrderedSet_h_GNUSTEP_BASE_INCLUDE */

View file

@ -172,6 +172,7 @@ GSFormat.m \
GSHTTPAuthentication.m \
GSHTTPURLHandle.m \
GSICUString.m \
GSOrderedSet.m \
GSPrivateHash.m \
GSQuickSort.m \
GSRunLoopWatcher.m \
@ -256,6 +257,7 @@ NSObjCRuntime.m \
NSObject.m \
NSObject+NSComparisonMethods.m \
NSOperation.m \
NSOrderedSet.m \
NSPage.m \
NSPathUtilities.m \
NSPipe.m \
@ -426,6 +428,7 @@ NSNumberFormatter.h \
NSObjCRuntime.h \
NSObject.h \
NSOperation.h \
NSOrderedSet.h \
NSPathUtilities.h \
NSPointerArray.h \
NSPointerFunctions.h \

392
Source/GSOrderedSet.m Normal file
View file

@ -0,0 +1,392 @@
/** Concrete implementation of GSOrderedSet and GSMutableOrderedSet
based on GNU NSOrderedSet and NSMutableOrderedSet classes
Copyright (C) 2019 Free Software Foundation, Inc.
Written by: Gregory Casamento <greg.casamento@gmail.com>
Created: May 17 2019
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
_version 2 of the License, or (at your option) any later _version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02111 USA.
*/
#import "common.h"
#import "Foundation/NSOrderedSet.h"
#import "Foundation/NSAutoreleasePool.h"
#import "Foundation/NSArray.h"
#import "Foundation/NSEnumerator.h"
#import "Foundation/NSException.h"
#import "Foundation/NSPortCoder.h"
#import "Foundation/NSIndexSet.h"
#import "Foundation/NSKeyedArchiver.h"
#import "Foundation/NSValue.h"
#import "Foundation/NSDictionary.h"
#import "GNUstepBase/GSObjCRuntime.h"
#import "GSPrivate.h"
#import "GSFastEnumeration.h"
#import "GSDispatch.h"
#import "GSSorting.h"
#define GSI_ARRAY_TYPES GSUNION_OBJ
#import "GNUstepBase/GSIArray.h"
#define GSI_MAP_HAS_VALUE 0
#define GSI_MAP_KTYPES GSUNION_OBJ
#define GSI_MAP_RETAIN_KEY(M, X)
#define GSI_MAP_RELEASE_KEY(M, X)
#include "GNUstepBase/GSIMap.h"
@interface GSOrderedSet : NSOrderedSet
{
@public
GSIArray_t array;
GSIMapTable_t map;
}
@end
@interface GSMutableOrderedSet : NSMutableOrderedSet
{
@public
GSIArray_t array;
GSIMapTable_t map;
@private
NSUInteger _version;
}
@end
@interface GSOrderedSetEnumerator : NSEnumerator
{
GSOrderedSet *set;
unsigned current;
unsigned count;
}
@end
@interface GSOrderedSetEnumeratorReverse : GSOrderedSetEnumerator
@end
@implementation GSOrderedSetEnumerator
- (id) initWithOrderedSet: (NSOrderedSet*)d
{
self = [super init];
if (self != nil)
{
set = (GSOrderedSet*)RETAIN(d);
current = 0;
count = GSIArrayCount(&set->array);
}
return self;
}
- (id) nextObject
{
if (current < count)
{
GSIArrayItem item = GSIArrayItemAtIndex(&set->array, current);
current++;
return (id)(item.obj);
}
return nil;
}
- (void) dealloc
{
RELEASE(set);
[super dealloc];
}
@end
@implementation GSOrderedSetEnumeratorReverse
- (id) initWithOrderedSet: (GSOrderedSet*)d
{
self = [super initWithOrderedSet: d];
if (self != nil)
{
current = GSIArrayCount(&set->array);
}
return self;
}
- (id) nextObject
{
GSIArrayItem item;
if (current == 0)
{
return nil;
}
item = GSIArrayItemAtIndex(&set->array, --current);
return (id)(item.obj);
}
@end
@implementation GSOrderedSet
static Class setClass;
static Class mutableSetClass;
+ (void) initialize
{
if (self == [GSOrderedSet class])
{
setClass = [GSOrderedSet class];
mutableSetClass = [GSMutableOrderedSet class];
}
}
- (id) copyWithZone: (NSZone*)z
{
return RETAIN(self);
}
- (void) dealloc
{
GSIArrayEmpty(&array);
GSIMapEmptyMap(&map);
[super dealloc];
}
- (NSUInteger) hash
{
return [self count];
}
- (instancetype) init
{
return [self initWithObjects: NULL count: 0];
}
- (NSEnumerator*) objectEnumerator
{
return AUTORELEASE([[GSOrderedSetEnumerator alloc] initWithOrderedSet: self]);
}
- (NSEnumerator*) reverseObjectEnumerator
{
return AUTORELEASE([[GSOrderedSetEnumeratorReverse alloc] initWithOrderedSet: self]);
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
NSUInteger size = GSPrivateMemorySize(self, exclude);
if (size > 0)
{
NSUInteger count = [self count];
NSUInteger i = 0;
for (i = 0; i < count; i++)
{
GSIArrayItem item = GSIArrayItemAtIndex(&array, i);
size += [item.obj sizeInBytesExcluding: exclude];
}
}
return size;
}
// Put required overrides here...
- (BOOL) containsObject: (id)anObject
{
if (anObject != nil)
{
GSIMapNode node = GSIMapNodeForKey(&map, (GSIMapKey)anObject);
if (node != 0)
{
return YES;
}
}
return NO;
}
- (NSUInteger) count
{
return GSIArrayCount(&array);
}
- (id) objectAtIndex: (NSUInteger)index
{
GSIArrayItem item = GSIArrayItemAtIndex(&array, index);
return item.obj;
}
- (void) getObjects: (__unsafe_unretained id[])aBuffer range: (NSRange)aRange
{
NSUInteger i, j = 0;
NSUInteger c = GSIArrayCount(&array);
NSUInteger e = NSMaxRange(aRange);
GS_RANGE_CHECK(aRange, c);
for (i = aRange.location; i < e; i++)
{
GSIArrayItem item = GSIArrayItemAtIndex(&array, i);
aBuffer[j++] = item.obj;
}
}
/* Designated initialiser */
- (id) initWithObjects: (const id*)objs count: (NSUInteger)c
{
NSUInteger i = 0;
// Initialize and fill the set.
GSIArrayInitWithZoneAndCapacity(&array, [self zone], c);
GSIMapInitWithZoneAndCapacity(&map, [self zone], c);
for (i = 0; i < c; i++)
{
id obj = objs[i];
if (obj == nil)
{
DESTROY(self);
[NSException raise: NSInvalidArgumentException
format: @"Tried to init set with nil value"];
}
if (![self containsObject: obj])
{
GSIArrayItem item;
item.obj = obj;
GSIArrayAddItem(&array, item);
GSIMapAddKey(&map, (GSIMapKey)obj);
}
}
return self;
}
@end
@implementation GSMutableOrderedSet
+ (void) initialize
{
if (self == [GSMutableOrderedSet class])
{
GSObjCAddClassBehavior(self, [GSOrderedSet class]);
}
}
- (void) insertObject: (id)object atIndex: (NSUInteger)index
{
if (object == nil)
{
[NSException raise: NSInvalidArgumentException
format: @"Tried to add nil to set"];
}
else
{
if ([self containsObject: object] == NO)
{
GSIArrayItem item;
_version++;
item.obj = object;
GSIArrayInsertItem(&array, item, index);
GSIMapAddKey(&map, (GSIMapKey)object);
_version++;
}
}
}
- (void) removeObjectAtIndex: (NSUInteger)index
{
GSIArrayItem item = GSIArrayItemAtIndex(&array, index);
_version++;
GSIArrayRemoveItemAtIndex(&array, index);
GSIMapRemoveKey(&map, (GSIMapKey)item.obj);
_version++;
}
- (id) init
{
return [self initWithCapacity: 0];
}
/* Designated initialiser */
- (id) initWithCapacity: (NSUInteger)cap
{
GSIArrayInitWithZoneAndCapacity(&array, [self zone], cap);
GSIMapInitWithZoneAndCapacity(&map, [self zone], cap);
return self;
}
- (id) initWithObjects: (const id*)objects
count: (NSUInteger)count
{
NSUInteger i = 0;
// Init and fill set
self = [self initWithCapacity: count];
if (self != nil)
{
for (i = 0; i < count; i++)
{
id anObject = objects[i];
[self addObject: anObject];
}
}
return self;
}
- (BOOL) makeImmutable
{
GSClassSwizzle(self, [GSOrderedSet class]);
return YES;
}
- (id) makeImmutableCopyOnFail: (BOOL)force
{
GSClassSwizzle(self, [GSOrderedSet class]);
return self;
}
- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState *)state
objects: (__unsafe_unretained id[])stackbuf
count: (NSUInteger)len
{
NSInteger count;
/* This is cached in the caller at the start and compared at each
* iteration. If it changes during the iteration then
* objc_enumerationMutation() will be called, throwing an exception.
*/
state->mutationsPtr = &_version;
count = MIN(len, [self count] - state->state);
/* If a mutation has occurred then it's possible that we are being asked to
* get objects from after the end of the array. Don't pass negative values
* to memcpy.
*/
if (count > 0)
{
[self getObjects: stackbuf range: NSMakeRange(state->state, count)];
state->state += count;
}
else
{
count = 0;
}
state->itemsPtr = stackbuf;
return count;
}
@end

View file

@ -1219,7 +1219,6 @@ compare(id elem1, id elem2, void* context)
return NSNotFound;
}
/**
* Returns a string formed by concatenating the objects in the receiver,
* with the specified separator string inserted between each part.
@ -1884,9 +1883,32 @@ compare(id elem1, id elem2, void* context)
options: (NSEnumerationOptions)opts
passingTest: (GSPredicateBlock)predicate
{
return [[self objectsAtIndexes: indexSet]
indexesOfObjectsWithOptions: opts
passingTest: predicate];
NSIndexSet *rindexes =[[self objectsAtIndexes: indexSet]
indexesOfObjectsWithOptions: opts
passingTest: predicate];
NSUInteger count = [indexSet count];
NSUInteger resultCount = [rindexes count];
NSUInteger indexArray[count], resultIndexArray[resultCount];
NSMutableIndexSet *resultSet = [NSMutableIndexSet indexSet];
NSUInteger i = 0;
[indexSet getIndexes: indexArray
maxCount: count
inIndexRange: NULL];
[rindexes getIndexes: resultIndexArray
maxCount: resultCount
inIndexRange: NULL];
// interate over indexes and collect the matching ones..
for(i = 0; i < resultCount; i++)
{
NSUInteger rindx = resultIndexArray[i];
NSUInteger indx = indexArray[rindx];
[resultSet addIndex: indx];
}
return resultSet;
}
- (NSUInteger) indexOfObjectWithOptions: (NSEnumerationOptions)opts
@ -1959,9 +1981,17 @@ compare(id elem1, id elem2, void* context)
options: (NSEnumerationOptions)opts
passingTest: (GSPredicateBlock)predicate
{
return [[self objectsAtIndexes: indexSet]
indexOfObjectWithOptions: 0
passingTest: predicate];
NSUInteger index = [[self objectsAtIndexes: indexSet]
indexOfObjectWithOptions: 0
passingTest: predicate];
NSUInteger count = [indexSet count];
NSUInteger indexArray[count];
[indexSet getIndexes: indexArray
maxCount: count
inIndexRange: NULL];
return indexArray[index];
}
@end

View file

@ -949,6 +949,19 @@ compareIt(id o1, id o2, void* context)
return k;
}
- (NSArray *)keysSortedByValueUsingComparator: (NSComparator)cmptr
{
return [self keysSortedByValueWithOptions:0
usingComparator:cmptr];
}
- (NSArray *)keysSortedByValueWithOptions: (NSSortOptions)opts
usingComparator: (NSComparator)cmptr
{
return [[self allKeys] sortedArrayWithOptions: opts
usingComparator: cmptr];
}
/**
* Multiple version of [-objectForKey:]. Objects for each key in keys are
* looked up and placed into return array in same order. For each key that

1795
Source/NSOrderedSet.m Normal file

File diff suppressed because it is too large Load diff

View file

@ -197,7 +197,7 @@ static Class NSMutableSet_concrete_class;
else
{
unsigned count = [self count];
NSEnumerator *e = [self objectEnumerator];
NSEnumerator *e = [self objectEnumerator];
id o;
[aCoder encodeValueOfObjCType: @encode(unsigned) at: &count];

View file

@ -1,32 +1,370 @@
#import "ObjectTesting.h"
#import <Foundation/NSAutoreleasePool.h>
/*
#import <Foundation/NSOrderedSet.h>
*/
static NSString *stringData = @"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
@"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"
@"<plist version=\"1.0\">"
@"<dict>"
@" <key>$archiver</key>"
@" <string>NSKeyedArchiver</string>"
@" <key>$objects</key>"
@" <array>"
@" <string>$null</string>"
@" <dict>"
@" <key>$class</key>"
@" <dict>"
@" <key>CF$UID</key>"
@" <integer>14</integer>"
@" </dict>"
@" <key>NS.object.0</key>"
@" <dict>"
@" <key>CF$UID</key>"
@" <integer>2</integer>"
@" </dict>"
@" <key>NS.object.1</key>"
@" <dict>"
@" <key>CF$UID</key>"
@" <integer>3</integer>"
@" </dict>"
@" <key>NS.object.10</key>"
@" <dict>"
@" <key>CF$UID</key>"
@" <integer>12</integer>"
@" </dict>"
@" <key>NS.object.11</key>"
@" <dict>"
@" <key>CF$UID</key>"
@" <integer>13</integer>"
@" </dict>"
@" <key>NS.object.2</key>"
@" <dict>"
@" <key>CF$UID</key>"
@" <integer>4</integer>"
@" </dict>"
@" <key>NS.object.3</key>"
@" <dict>"
@" <key>CF$UID</key>"
@" <integer>5</integer>"
@" </dict>"
@" <key>NS.object.4</key>"
@" <dict>"
@" <key>CF$UID</key>"
@" <integer>6</integer>"
@" </dict>"
@" <key>NS.object.5</key>"
@" <dict>"
@" <key>CF$UID</key>"
@" <integer>7</integer>"
@" </dict>"
@" <key>NS.object.6</key>"
@" <dict>"
@" <key>CF$UID</key>"
@" <integer>8</integer>"
@" </dict>"
@" <key>NS.object.7</key>"
@" <dict>"
@" <key>CF$UID</key>"
@" <integer>9</integer>"
@" </dict>"
@" <key>NS.object.8</key>"
@" <dict>"
@" <key>CF$UID</key>"
@" <integer>10</integer>"
@" </dict>"
@" <key>NS.object.9</key>"
@" <dict>"
@" <key>CF$UID</key>"
@" <integer>11</integer>"
@" </dict>"
@" </dict>"
@" <string>Now</string>"
@" <string>is</string>"
@" <string>the</string>"
@" <string>time</string>"
@" <string>for</string>"
@" <string>all</string>"
@" <string>Horrible</string>"
@" <string>men</string>"
@" <string>to</string>"
@" <string>Flee From</string>"
@" <string>the aid</string>"
@" <string>of their country</string>"
@" <dict>"
@" <key>$classes</key>"
@" <array>"
@" <string>NSMutableOrderedSet</string>"
@" <string>NSOrderedSet</string>"
@" <string>NSObject</string>"
@" </array>"
@" <key>$classname</key>"
@" <string>NSMutableOrderedSet</string>"
@" </dict>"
@" </array>"
@" <key>$top</key>"
@" <dict>"
@" <key>root</key>"
@" <dict>"
@" <key>CF$UID</key>"
@" <integer>1</integer>"
@" </dict>"
@" </dict>"
@" <key>$version</key>"
@" <integer>100000</integer>"
@"</dict>"
@"</plist>";
int main()
{
START_SET("NSOrderedSet base")
/*
NSOrderedSet *testObj;
NSOrderedSet *testObj, *testObj2;
NSMutableOrderedSet *mutableTest1, *mutableTest2;
NSMutableArray *testObjs = [NSMutableArray new];
NSData *data = [stringData dataUsingEncoding: NSUTF8StringEncoding];
NSMutableSet *testSet;
testObj = [NSOrderedSet new];
[testObjs addObject: testObj];
PASS(testObj != nil && [testObj count] == 0,
"can create an empty ordered set");
testObj = [NSOrderedSet setWithObject: @"Hello"];
"can create an empty ordered set");
testObj = [NSOrderedSet orderedSetWithObject: @"Hello"];
[testObjs addObject: testObj];
PASS(testObj != nil && [testObj count] == 1,
"can create an ordered set with one element");
"can create an ordered set with one element");
id objs[] = {@"Hello", @"Hello1"};
testObj = [NSOrderedSet orderedSetWithObjects: objs count: 2];
[testObjs addObject: testObj];
PASS(testObj != nil && [testObj count] == 2,
"can create an ordered set with multi element");
id objs1[] = {@"Hello", @"Hello"};
testObj = [NSOrderedSet orderedSetWithObjects: objs1 count: 2];
[testObjs addObject: testObj];
PASS(testObj != nil && [testObj count] == 1,
"cannot create an ordered set with multiple like elements");
NSMutableArray *arr = [NSMutableArray array];
[arr addObject: @"Hello"];
[arr addObject: @"World"];
testObj = [NSOrderedSet orderedSetWithArray: arr];
[testObjs addObject: testObj];
PASS(testObj != nil && [testObj count] == 2,
"Is able to initialize with array");
id objs3[] = {@"Hello"};
id objc4[] = {@"World"};
testObj = [NSOrderedSet orderedSetWithObjects: objs3 count: 1];
[testObjs addObject: testObj];
testObj2 = [NSOrderedSet orderedSetWithObjects: objc4 count: 1];
[testObjs addObject: testObj2];
BOOL result = [testObj intersectsOrderedSet: testObj2];
PASS(result == NO,
"Sets do not intersect!");
id objs5[] = {@"Hello"};
id objc6[] = {@"Hello"};
testObj = [NSOrderedSet orderedSetWithObjects: objs5 count: 1];
[testObjs addObject: testObj];
testObj2 = [NSOrderedSet orderedSetWithObjects: objc6 count: 1];
[testObjs addObject: testObj2];
BOOL result1 = [testObj intersectsOrderedSet: testObj2];
PASS(result1 == YES,
"Sets do intersect!");
id o1 = @"Hello";
id o2 = @"World";
mutableTest1 = [NSMutableOrderedSet orderedSet];
[mutableTest1 addObject: o1];
[testObjs addObject: mutableTest1];
mutableTest2 = [NSMutableOrderedSet orderedSet];
[mutableTest2 addObject: o2];
[testObjs addObject: mutableTest2];
[mutableTest1 unionOrderedSet: mutableTest2];
PASS(mutableTest1 != nil && mutableTest2 != nil && [mutableTest1 count] == 2,
"mutableSets union properly");
id o3 = @"Hello";
id o4 = @"World";
mutableTest1 = [NSMutableOrderedSet orderedSet];
[mutableTest1 addObject: o3];
[testObjs addObject: mutableTest1];
mutableTest2 = [NSMutableOrderedSet orderedSet];
[mutableTest2 addObject: o4];
[testObjs addObject: mutableTest2];
[mutableTest1 intersectOrderedSet: mutableTest2];
PASS(mutableTest1 != nil && mutableTest2 != nil && [mutableTest1 count] == 0,
"mutableSets do not intersect");
id o5 = @"Hello";
id o6 = @"Hello";
mutableTest1 = [NSMutableOrderedSet orderedSet];
[mutableTest1 addObject: o5];
[testObjs addObject: mutableTest1];
mutableTest2 = [NSMutableOrderedSet orderedSet];
[mutableTest2 addObject: o6];
[testObjs addObject: mutableTest2];
[mutableTest1 intersectOrderedSet: mutableTest2];
PASS(mutableTest1 != nil && mutableTest2 != nil && [mutableTest1 count] == 1,
"mutableSets do intersect");
id o7 = @"Hello";
id o8 = @"World";
mutableTest1 = [NSMutableOrderedSet orderedSet];
[mutableTest1 addObject: o7];
[mutableTest1 addObject: o8];
[testObjs addObject: mutableTest1];
mutableTest2 = [NSMutableOrderedSet orderedSet];
[mutableTest2 addObject: o7];
[testObjs addObject: mutableTest2];
BOOL isSubset = [mutableTest2 isSubsetOfOrderedSet: mutableTest1];
PASS(isSubset,
"mutableTest2 is subset of mutableTest1");
testSet = [NSMutableSet set];
[testSet addObject: o7];
[testSet addObject: o8];
isSubset = [mutableTest2 isSubsetOfSet: testSet];
PASS(isSubset,
"mutableTest2 is subset of testSet");
id o9 = @"Hello";
id o10 = @"World";
id o11 = @"Ready";
mutableTest1 = [NSMutableOrderedSet orderedSet];
[mutableTest1 addObject: o9];
[testObjs addObject: mutableTest1];
mutableTest2 = [NSMutableOrderedSet orderedSet];
[mutableTest2 addObject: o10];
[mutableTest2 addObject: o9];
[testObjs addObject: mutableTest2];
isSubset = [mutableTest2 isSubsetOfOrderedSet: mutableTest1];
PASS(isSubset == NO,
"mutableTest2 is not subset of mutableTest1");
testSet = [NSMutableSet set];
[testSet addObject: o9];
isSubset = [mutableTest2 isSubsetOfSet: testSet];
PASS(isSubset == NO,
"mutableTest2 is not subset of testSet");
o9 = @"Hello";
o10 = @"World";
o11 = @"Ready";
id o12 = @"ToGo";
mutableTest1 = [NSMutableOrderedSet orderedSet];
[mutableTest1 addObject: o9];
[mutableTest1 addObject: o10];
[mutableTest1 addObject: o12];
[mutableTest1 addObject: o11];
[testObjs addObject: mutableTest1];
mutableTest2 = [NSMutableOrderedSet orderedSet];
[mutableTest2 addObject: o9];
[mutableTest2 addObject: o10];
[testObjs addObject: mutableTest2];
isSubset = [mutableTest2 isSubsetOfOrderedSet: mutableTest1];
PASS(isSubset,
"mutableTest2 is subset of mutableTest1");
testSet = [NSMutableSet set];
[testSet addObject: o9];
[testSet addObject: o10];
[testSet addObject: o12];
[testSet addObject: o11];
isSubset = [mutableTest2 isSubsetOfSet: testSet];
PASS(isSubset,
"mutableTest2 is subset of testSet");
o9 = @"Hello";
o10 = @"World";
o11 = @"Ready";
o12 = @"ToGo";
mutableTest1 = [NSMutableOrderedSet orderedSet];
[mutableTest1 addObject: o9];
[mutableTest1 addObject: o10];
[mutableTest1 addObject: o12];
[mutableTest1 addObject: o11];
[testObjs addObject: mutableTest1];
PASS([mutableTest1 isEqual: mutableTest1],
"mutableTest1 is equal to itself");
o9 = @"Hello";
o10 = @"World";
o11 = @"Ready";
o12 = @"ToGo";
NSMutableOrderedSet *mutableTest3 = [NSMutableOrderedSet orderedSet];
[mutableTest3 addObject: o9];
[mutableTest3 addObject: o10];
[mutableTest3 addObject: o12];
[mutableTest3 addObject: o11];
[mutableTest3 insertObject: @"Hello" atIndex: 2];
[testObjs addObject: mutableTest3];
PASS([mutableTest3 isEqual: mutableTest1] == YES,
"Insert at index does not replace existing object");
NSMutableOrderedSet *mutableTest4 = [NSMutableOrderedSet orderedSet];
[mutableTest4 addObject: @"Now"];
[mutableTest4 addObject: @"is"];
[mutableTest4 addObject: @"the"];
[mutableTest4 addObject: @"time"];
[mutableTest4 addObject: @"for"];
[mutableTest4 addObject: @"all"];
[mutableTest4 addObject: @"Good"];
[mutableTest4 addObject: @"men"];
[mutableTest4 addObject: @"to"];
[mutableTest4 addObject: @"come"];
[mutableTest4 addObject: @"to the aid"];
[mutableTest4 addObject: @"of their country"];
[mutableTest4 moveObjectsAtIndexes: [NSIndexSet indexSetWithIndex: 3] toIndex: 10];
[testObjs addObject: mutableTest4];
PASS([[mutableTest4 objectAtIndex: 10] isEqual: @"time"] == YES,
"Move to index moves to correct index");
NSMutableOrderedSet *mutableTest5 = [NSMutableOrderedSet orderedSet];
[mutableTest5 addObject: @"Now"];
[mutableTest5 addObject: @"is"];
[mutableTest5 addObject: @"the"];
[mutableTest5 exchangeObjectAtIndex: 0 withObjectAtIndex: 2];
[testObjs addObject: mutableTest5];
PASS([[mutableTest5 objectAtIndex: 0] isEqual: @"the"] == YES &&
[[mutableTest5 objectAtIndex: 2] isEqual: @"Now"] == YES,
"Exchanges indexes properly");
//NSLog(@"RESULT: %@",mutableTest4);
mutableTest4 = [NSMutableOrderedSet orderedSet];
[mutableTest4 addObject: @"Now"];
[mutableTest4 addObject: @"is"];
[mutableTest4 addObject: @"the"];
[mutableTest4 addObject: @"time"];
[mutableTest4 addObject: @"for"];
[mutableTest4 addObject: @"all"];
[mutableTest4 addObject: @"Good"];
[mutableTest4 addObject: @"men"];
[mutableTest4 addObject: @"to"];
[mutableTest4 addObject: @"come to"];
[mutableTest4 addObject: @"the aid"];
[mutableTest4 addObject: @"of their country"];
NSMutableIndexSet *is = [NSMutableIndexSet indexSetWithIndex: 6];
[is addIndex: 9];
NSMutableArray *array = [NSMutableArray arrayWithObjects: @"Horrible", @"Flee From", nil];
[mutableTest4 replaceObjectsAtIndexes: is
withObjects: array];
[testObjs addObject: mutableTest4];
PASS([[mutableTest4 objectAtIndex: 9] isEqual: @"Flee From"] == YES,
"replaceObjectsAtIndexes: adds to correct indexes");
id uobj = [NSKeyedUnarchiver unarchiveObjectWithData: data];
PASS((uobj != nil &&
[uobj isKindOfClass: [NSMutableOrderedSet class]] &&
[uobj containsObject: @"Now"]),
"Object unarchives correctly from macOS archive")
test_NSObject(@"NSOrderedSet", testObjs);
test_NSCoding(testObjs);
test_NSCopying(@"NSOrderedSet", @"NSMutableOrderedSet", testObjs, YES, NO);
test_NSMutableCopying(@"NSOrderedSet", @"NSMutableOrderedSet", testObjs);
*/
END_SET("NSOrderedSet base")
return 0;

View file

@ -0,0 +1,84 @@
#import "Testing.h"
#import <Foundation/NSOrderedSet.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSIndexSet.h>
#import <Foundation/NSString.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSValue.h>
static NSUInteger fooCount = 0;
static NSUInteger lastIndex = NSNotFound;
int main()
{
START_SET("NSOrderedSet Blocks")
# ifndef __has_feature
# define __has_feature(x) 0
# endif
# if __has_feature(blocks)
NSAutoreleasePool *arp = [NSAutoreleasePool new];
// Code for test here...
NSMutableOrderedSet *mutableTest4 = [NSMutableOrderedSet orderedSet];
[mutableTest4 addObject:@"Now"];
[mutableTest4 addObject:@"is"];
[mutableTest4 addObject:@"the"];
[mutableTest4 addObject:@"time"];
[mutableTest4 addObject:@"for"];
[mutableTest4 addObject:@"all"];
[mutableTest4 addObject:@"Good"];
[mutableTest4 addObject:@"men"];
[mutableTest4 addObject:@"to"];
[mutableTest4 addObject:@"come to"];
[mutableTest4 addObject:@"the aid"];
[mutableTest4 addObject:@"of their country"];
NSMutableIndexSet *is = [NSMutableIndexSet indexSetWithIndex:6];
[is addIndex: 9];
NSMutableArray *array = [NSMutableArray arrayWithObjects:@"Horrible", @"Flee From", nil];
[mutableTest4 replaceObjectsAtIndexes: is
withObjects: array];
NSUInteger index = [mutableTest4 indexOfObjectPassingTest:^BOOL(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
return [obj isEqualToString:@"Horrible"];
}];
// NSLog(@"Index = %d", index);
PASS(index == 6, "Found correct index using indexOfObjectPassingTest:");
NSIndexSet *indexes = [mutableTest4 indexesOfObjectsPassingTest: ^BOOL(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
return [obj isEqualToString:@"Horrible"] ||
[obj isEqualToString: @"Flee From"];
}];
PASS([indexes containsIndex: 6] && [indexes containsIndex: 9], "Returns correct indexes");
indexes = [mutableTest4
indexesOfObjectsWithOptions:0
passingTest:^BOOL(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
return [obj isEqualToString:@"Horrible"] || [obj isEqualToString:@"Flee From"];
}];
NSLog(@"indexes = %@",indexes);
PASS([indexes containsIndex:6] && [indexes containsIndex:9],
"indexesOfObjectsWithOptions:passingTest: returns correct indexes");
index = [mutableTest4 indexOfObjectAtIndexes:[NSIndexSet indexSetWithIndex: 6]
options:0
passingTest:^BOOL(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
return [obj isEqualToString:@"Horrible"];
}];
PASS(index == 6, "indexOfObjectAtIndexes:... Returns correct index");
NSMutableIndexSet *iset = [NSMutableIndexSet indexSetWithIndex: 6];
[iset addIndex: 9];
indexes = [mutableTest4 indexesOfObjectsAtIndexes: iset
options:0
passingTest:^BOOL(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
return [obj isEqualToString:@"Horrible"] || [obj isEqualToString:@"Flee From"];
}];
NSLog(@"indexes = %@",indexes);
PASS([indexes containsIndex:6] && [indexes containsIndex:9], "indexesOfObjectsAtIndexes... returns correct indexes");
# else
SKIP("No Blocks support in the compiler.")
# endif
END_SET("NSOrderedSet Blocks")
return 0;
}