fixup for removal from mutable array

This commit is contained in:
rfm 2025-01-01 13:39:13 +00:00
parent 46d19b5dd5
commit bbd1f03183
3 changed files with 235 additions and 43 deletions

View file

@ -30,14 +30,15 @@
@interface NSKeyValueMutableArray : NSMutableArray
{
@protected
id object;
NSString *key;
id object;
NSString *key;
NSMutableArray *array;
BOOL otherChangeInProgress;
BOOL notifiesObservers;
}
+ (NSKeyValueMutableArray *) arrayForKey: (NSString *)aKey ofObject: (id)anObject;
+ (NSKeyValueMutableArray *) arrayForKey: (NSString*)aKey
ofObject: (id)anObject;
- (id) initWithKey: (NSString *)aKey ofObject: (id)anObject;
@end
@ -51,10 +52,10 @@
}
+ (id) arrayForKey: (NSString *)aKey ofObject: (id)anObject
withCapitalizedKey: (const char *)capitalized;
withCapitalizedKey: (const char *)capitalized;
- (id) initWithKey: (NSString *)aKey ofObject: (id)anObject
withCapitalizedKey: (const char *)capitalized;
withCapitalizedKey: (const char *)capitalized;
@end
@ -65,10 +66,10 @@
}
+ (id) arrayForKey: (NSString *)aKey ofObject: (id)anObject
withCapitalizedKey: (const char *)capitalized;
withCapitalizedKey: (const char *)capitalized;
- (id) initWithKey: (NSString *)aKey ofObject: (id)anObject
withCapitalizedKey: (const char *)capitalized;
withCapitalizedKey: (const char *)capitalized;
@end
@ -84,6 +85,12 @@
@end
/* NB. For removal of objects we can remove multiple objects at the same
* time and the notifications are sent with an NSIndexSet specifying the
* indices which are being altered. We therefore funnuel all the other
* removal methods through the -removeObjectsAtIndexes: method so that
* the subclasses only need to implement that one themselves.
*/
@implementation NSKeyValueMutableArray
+ (NSKeyValueMutableArray *) arrayForKey: (NSString *)aKey
@ -93,6 +100,7 @@
unsigned size = [aKey maximumLengthOfBytesUsingEncoding:
NSUTF8StringEncoding];
char keybuf[size + 1];
[aKey getCString: keybuf
maxLength: size + 1
encoding: NSUTF8StringEncoding];
@ -126,8 +134,8 @@
object = anObject;
key = [aKey copy];
otherChangeInProgress = NO;
notifiesObservers =
[[anObject class] automaticallyNotifiesObserversForKey: aKey];
notifiesObservers
= [[anObject class] automaticallyNotifiesObserversForKey: aKey];
}
return self;
}
@ -155,9 +163,21 @@
[self insertObject: anObject atIndex: [self count]];
}
- (void) removeFirstObject
{
NSUInteger count = [self count];
if (0 == count)
{
return;
}
[self removeObjectAtIndex: 0];
}
- (void) removeLastObject
{
NSUInteger count = [self count];
if (0 == count)
{
return;
@ -165,19 +185,78 @@
[self removeObjectAtIndex: (count - 1)];
}
- (void) removeObject: (id)anObject
{
NSUInteger count = [self count];
if (count > 0)
{
NSMutableIndexSet *indexes = nil;
while (count-- > 0)
{
if ([[self objectAtIndex: count] isEqual: anObject])
{
if (nil == indexes)
{
indexes = [NSMutableIndexSet indexSet];
}
[indexes addIndex: count];
}
}
if (indexes)
{
[self removeObjectsAtIndexes: indexes];
}
}
}
- (void) removeObjectAtIndex: (NSUInteger)index
{
if (index != NSNotFound)
{
[self removeObjectsAtIndexes: [NSIndexSet indexSetWithIndex: index]];
}
}
- (void) removeObjectsFromIndices: (NSUInteger*)indices
numIndices: (NSUInteger)count
{
if (count > 0)
{
NSMutableIndexSet *indexes = nil;
while (count-- > 0)
{
if (indices[count] != NSNotFound)
{
if (nil == indexes)
{
indexes = [NSMutableIndexSet indexSet];
}
[indexes addIndex: indices[count]];
}
}
if (indexes)
{
[self removeObjectsAtIndexes: indexes];
}
}
}
@end
@implementation NSKeyValueFastMutableArray
+ (id) arrayForKey: (NSString *)aKey ofObject: (id)anObject
withCapitalizedKey: (const char *)capitalized
withCapitalizedKey: (const char *)capitalized
{
return [[[self alloc] initWithKey: aKey ofObject: anObject
withCapitalizedKey: capitalized] autorelease];
}
- (id) initWithKey: (NSString *)aKey ofObject: (id)anObject
withCapitalizedKey: (const char *)capitalized
withCapitalizedKey: (const char *)capitalized
{
SEL insert;
SEL remove;
@ -227,24 +306,33 @@
[super dealloc];
}
- (void) removeObjectAtIndex: (NSUInteger)index
- (void) removeObjectsAtIndexes: (NSIndexSet*)indexes
{
NSIndexSet *indexes = nil;
NSUInteger index = [indexes lastIndex];
if (nil == indexes || NSNotFound == index)
{
return;
}
if (notifiesObservers && !otherChangeInProgress)
{
indexes = [NSIndexSet indexSetWithIndex: index];
[object willChange: NSKeyValueChangeRemoval
valuesAtIndexes: indexes
valuesAtIndexes: indexes
forKey: key];
}
[removeObjectInvocation setArgument: &index atIndex: 2];
[removeObjectInvocation invoke];
while ((index = [indexes indexLessThanIndex: index]) != NSNotFound)
{
[removeObjectInvocation setArgument: &index atIndex: 2];
[removeObjectInvocation invoke];
}
if (notifiesObservers && !otherChangeInProgress)
{
[object didChange: NSKeyValueChangeRemoval
valuesAtIndexes: indexes
forKey: key];
forKey: key];
}
}
@ -256,8 +344,8 @@
{
indexes = [NSIndexSet indexSetWithIndex: index];
[object willChange: NSKeyValueChangeInsertion
valuesAtIndexes: indexes
forKey: key];
valuesAtIndexes: indexes
forKey: key];
}
[insertObjectInvocation setArgument: &anObject atIndex: 2];
[insertObjectInvocation setArgument: &index atIndex: 3];
@ -265,7 +353,7 @@
if (notifiesObservers && !otherChangeInProgress)
{
[object didChange: NSKeyValueChangeInsertion
valuesAtIndexes: indexes
valuesAtIndexes: indexes
forKey: key];
}
}
@ -279,8 +367,8 @@
otherChangeInProgress = YES;
indexes = [NSIndexSet indexSetWithIndex: index];
[object willChange: NSKeyValueChangeReplacement
valuesAtIndexes: indexes
forKey: key];
valuesAtIndexes: indexes
forKey: key];
}
if (replaceObjectInvocation)
{
@ -296,26 +384,25 @@
if (notifiesObservers && !otherChangeInProgress)
{
[object didChange: NSKeyValueChangeReplacement
valuesAtIndexes: indexes
valuesAtIndexes: indexes
forKey: key];
otherChangeInProgress = NO;
}
}
@end
@implementation NSKeyValueSlowMutableArray
+ (id) arrayForKey: (NSString *)aKey ofObject: (id)anObject
withCapitalizedKey: (const char *)capitalized
withCapitalizedKey: (const char *)capitalized
{
return [[[self alloc] initWithKey: aKey ofObject: anObject
withCapitalizedKey: capitalized] autorelease];
withCapitalizedKey: capitalized] autorelease];
}
- (id) initWithKey: (NSString *)aKey ofObject: (id)anObject
withCapitalizedKey: (const char *)capitalized;
withCapitalizedKey: (const char *)capitalized;
{
SEL set = NSSelectorFromString([NSString stringWithFormat:
@ -337,21 +424,29 @@
return self;
}
- (void) removeObjectAtIndex: (NSUInteger)index
- (void) removeObjectsAtIndexes: (NSIndexSet*)indexes
{
NSIndexSet *indexes = nil;
NSMutableArray *temp;
NSUInteger index = [indexes lastIndex];
NSMutableArray *temp;
if (nil == indexes || NSNotFound == index)
{
return;
}
if (notifiesObservers && !otherChangeInProgress)
{
indexes = [NSIndexSet indexSetWithIndex: index];
[object willChange: NSKeyValueChangeRemoval
valuesAtIndexes: indexes
valuesAtIndexes: indexes
forKey: key];
}
temp = [NSMutableArray arrayWithArray: [object valueForKey: key]];
[temp removeObjectAtIndex: index];
while ((index = [indexes indexLessThanIndex: index]) != NSNotFound)
{
[temp removeObjectAtIndex: index];
}
[setArrayInvocation setArgument: &temp atIndex: 2];
[setArrayInvocation invoke];
@ -359,21 +454,21 @@
if (notifiesObservers && !otherChangeInProgress)
{
[object didChange: NSKeyValueChangeRemoval
valuesAtIndexes: indexes
valuesAtIndexes: indexes
forKey: key];
}
}
- (void) insertObject: (id)anObject atIndex: (NSUInteger)index
{
NSIndexSet *indexes = nil;
NSIndexSet *indexes = nil;
NSMutableArray *temp;
if (notifiesObservers && !otherChangeInProgress)
{
indexes = [NSIndexSet indexSetWithIndex: index];
[object willChange: NSKeyValueChangeInsertion
valuesAtIndexes: indexes
valuesAtIndexes: indexes
forKey: key];
}
@ -386,7 +481,7 @@
if (notifiesObservers && !otherChangeInProgress)
{
[object didChange: NSKeyValueChangeInsertion
valuesAtIndexes: indexes
valuesAtIndexes: indexes
forKey: key];
}
}
@ -400,7 +495,7 @@
{
indexes = [NSIndexSet indexSetWithIndex: index];
[object willChange: NSKeyValueChangeReplacement
valuesAtIndexes: indexes
valuesAtIndexes: indexes
forKey: key];
}
@ -414,12 +509,11 @@
if (notifiesObservers && !otherChangeInProgress)
{
[object didChange: NSKeyValueChangeReplacement
valuesAtIndexes: indexes
valuesAtIndexes: indexes
forKey: key];
}
}
@end
@ -447,11 +541,11 @@
maxLength: size + 1
encoding: NSUTF8StringEncoding];
if (!GSObjCFindVariable (anObject, cKeyPtr, &type, &size, &offset))
found = GSObjCFindVariable (anObject, ++cKeyPtr, &type, &size, &offset);
if (!GSObjCFindVariable(anObject, cKeyPtr, &type, &size, &offset))
found = GSObjCFindVariable(anObject, ++cKeyPtr, &type, &size, &offset);
if (found)
{
array = GSObjCGetVal (anObject, cKeyPtr, NULL, type, size, offset);
array = GSObjCGetVal(anObject, cKeyPtr, NULL, type, size, offset);
}
else
{
@ -482,9 +576,14 @@
}
}
- (void) removeObjectAtIndex: (NSUInteger)index
- (void) removeObjectsAtIndexes: (NSIndexSet*)indexes
{
NSIndexSet *indexes = nil;
NSUInteger index = [indexes lastIndex];
if (nil == indexes || NSNotFound == index)
{
return;
}
if (notifiesObservers)
{
@ -494,6 +593,10 @@
forKey: key];
}
[array removeObjectAtIndex: index];
while ((index = [indexes indexLessThanIndex: index]) != NSNotFound)
{
[array removeObjectAtIndex: index];
}
if (notifiesObservers)
{
[object didChange: NSKeyValueChangeRemoval
@ -526,6 +629,7 @@
{
NSIndexSet *indexes = nil;
NSUInteger count = [array count];
if (0 == count)
{
return;