27 - (id)mutableArrayValueForKey:(
id)aKey
29 return [[_CPKVCArray alloc] initWithKey:aKey forProxyObject:self];
32 - (id)mutableArrayValueForKeyPath:(
id)aKeyPath
34 var dotIndex = aKeyPath.indexOf(
".");
39 var firstPart = aKeyPath.substring(0, dotIndex),
40 lastPart = aKeyPath.substring(dotIndex + 1);
42 return [[
self valueForKeyPath:firstPart] mutableArrayValueForKeyPath:lastPart];
68 Function _replaceMany;
70 SEL _objectAtIndexSEL;
71 Function _objectAtIndex;
73 SEL _objectsAtIndexesSEL;
74 Function _objectsAtIndexes;
92 var ivars = class_copyIvarList(
self),
96 array[ivar_getName(ivars[count])] = nil;
101 - (id)initWithKey:(
id)aKey forProxyObject:(
id)anObject
106 _proxyObject = anObject;
108 var capitalizedKey = _key.charAt(0).toUpperCase() + _key.substring(1);
110 _insertSEL = sel_getName(
@"insertObject:in" + capitalizedKey +
"AtIndex:");
112 if ([_proxyObject respondsToSelector:_insertSEL])
113 _insert = [_proxyObject methodForSelector:_insertSEL];
115 _removeSEL = sel_getName(
@"removeObjectFrom" + capitalizedKey +
"AtIndex:");
117 if ([_proxyObject respondsToSelector:_removeSEL])
118 _remove = [_proxyObject methodForSelector:_removeSEL];
120 _replaceSEL = sel_getName(
@"replaceObjectIn" + capitalizedKey +
"AtIndex:withObject:");
122 if ([_proxyObject respondsToSelector:_replaceSEL])
123 _replace = [_proxyObject methodForSelector:_replaceSEL];
125 _insertManySEL = sel_getName(
@"insert" + capitalizedKey +
":atIndexes:");
127 if ([_proxyObject respondsToSelector:_insertManySEL])
128 _insertMany = [_proxyObject methodForSelector:_insertManySEL];
130 _removeManySEL = sel_getName(
@"remove" + capitalizedKey +
"AtIndexes:");
132 if ([_proxyObject respondsToSelector:_removeManySEL])
133 _removeMany = [_proxyObject methodForSelector:_removeManySEL];
135 _replaceManySEL = sel_getName(
@"replace" + capitalizedKey +
"AtIndexes:with" + capitalizedKey +
":");
137 if ([_proxyObject respondsToSelector:_replaceManySEL])
138 _replaceMany = [_proxyObject methodForSelector:_replaceManySEL];
140 _objectAtIndexSEL = sel_getName(
@"objectIn" + capitalizedKey +
"AtIndex:");
142 if ([_proxyObject respondsToSelector:_objectAtIndexSEL])
143 _objectAtIndex = [_proxyObject methodForSelector:_objectAtIndexSEL];
145 _objectsAtIndexesSEL = sel_getName(_key +
"AtIndexes:");
147 if ([_proxyObject respondsToSelector:_objectsAtIndexesSEL])
148 _objectsAtIndexes = [_proxyObject methodForSelector:_objectsAtIndexesSEL];
150 _countSEL = sel_getName(
@"countOf" + capitalizedKey);
152 if ([_proxyObject respondsToSelector:_countSEL])
153 _count = [_proxyObject methodForSelector:_countSEL];
155 _accessSEL = sel_getName(_key);
157 if ([_proxyObject respondsToSelector:_accessSEL])
158 _access = [_proxyObject methodForSelector:_accessSEL];
160 _setSEL = sel_getName(
@"set" + capitalizedKey +
":");
162 if ([_proxyObject respondsToSelector:_setSEL])
163 _set = [_proxyObject methodForSelector:_setSEL];
172 count = [
self count];
174 for (; i < count; i++)
175 [theCopy addObject:[self objectAtIndex:i]];
180 - (id)_representedObject
183 return _access(_proxyObject, _accessSEL);
185 return [_proxyObject valueForKey:_key];
188 - (void)_setRepresentedObject:(
id)anObject
191 return _set(_proxyObject, _setSEL, anObject);
193 [_proxyObject setValue:anObject forKey:_key];
199 return _count(_proxyObject, _countSEL);
201 return [[
self _representedObject] count];
204 - (CPUInteger)indexOfObject:(
id)anObject inRange:(CPRange)aRange
206 var index = aRange.location,
207 count = aRange.length,
208 shouldIsEqual = !!anObject.isa;
210 for (; index < count; ++index)
212 var
object = [
self objectAtIndex:index];
214 if (anObject ===
object || shouldIsEqual && !!
object.
isa && [anObject
isEqual:
object])
221 - (CPUInteger)indexOfObject:(
id)anObject
223 return [
self indexOfObject:anObject inRange:CPMakeRange(0, [
self count])];
226 - (CPUInteger)indexOfObjectIdenticalTo:(
id)anObject inRange:(CPRange)aRange
228 var index = aRange.location,
229 count = aRange.length;
231 for (; index < count; ++index)
232 if (anObject === [self objectAtIndex:index])
238 - (CPUInteger)indexOfObjectIdenticalTo:(
id)anObject
240 return [
self indexOfObjectIdenticalTo:anObject inRange:CPMakeRange(0, [
self count])];
243 - (id)objectAtIndex:(CPUInteger)anIndex
248 - (CPArray)objectsAtIndexes:(
CPIndexSet)theIndexes
250 if (_objectsAtIndexes)
251 return _objectsAtIndexes(_proxyObject, _objectsAtIndexesSEL, theIndexes);
258 while ((index = [theIndexes indexGreaterThanIndex:index]) !==
CPNotFound)
259 objects.push(_objectAtIndex(_proxyObject, _objectAtIndexSEL, index));
264 return [[
self _representedObject] objectsAtIndexes:theIndexes];
267 - (void)addObject:(
id)anObject
269 [
self insertObject:anObject atIndex:[
self count]];
272 - (void)addObjectsFromArray:(CPArray)anArray
275 count = [anArray count];
280 - (void)insertObject:(
id)anObject atIndex:(CPUInteger)anIndex
285 - (void)insertObjects:(CPArray)theObjects atIndexes:(
CPIndexSet)theIndexes
288 _insertMany(_proxyObject, _insertManySEL, theObjects, theIndexes);
291 var indexesArray = [];
294 for (var index = 0; index < [indexesArray count]; index++)
296 var objectIndex = [indexesArray objectAtIndex:index],
297 object = [theObjects objectAtIndex:index];
299 _insert(_proxyObject, _insertSEL,
object, objectIndex);
304 var target = [[
self _representedObject] copy];
306 [target insertObjects:theObjects atIndexes:theIndexes];
307 [
self _setRepresentedObject:target];
311 - (void)removeObject:(
id)anObject
313 [
self removeObject:anObject inRange:CPMakeRange(0, [
self count])];
316 - (void)removeObjectsInArray:(CPArray)theObjects
321 index = [theObjects count],
323 count = [
self count];
328 [indexes addIndex:position];
331 _removeMany(_proxyObject, _removeManySEL, indexes);
335 var index = [theObjects count],
339 while ((
position = [
self indexOfObject:[theObjects objectAtIndex:index]]) !==
CPNotFound)
340 _remove(_proxyObject, _removeSEL,
position);
345 var target = [[
self _representedObject] copy];
346 [target removeObjectsInArray:theObjects];
347 [
self _setRepresentedObject:target];
351 - (void)removeObject:(
id)theObject inRange:(CPRange)theRange
354 _remove(_proxyObject, _removeSEL, [
self indexOfObject:theObject inRange:theRange]);
355 else if (_removeMany)
357 var index = [
self indexOfObject:theObject inRange:theRange];
358 _removeMany(_proxyObject, _removeManySEL, [
CPIndexSet indexSetWithIndex:index]);
364 while ((index = [
self indexOfObject:theObject inRange:theRange]) !==
CPNotFound)
366 [
self removeObjectAtIndex:index];
372 - (void)removeLastObject
377 - (void)removeObjectAtIndex:(CPUInteger)anIndex
382 - (void)removeObjectsAtIndexes:(
CPIndexSet)theIndexes
385 _removeMany(_proxyObject, _removeManySEL, theIndexes);
392 _remove(_proxyObject, _removeSEL, index);
398 var target = [[
self _representedObject] copy];
399 [target removeObjectsAtIndexes:theIndexes];
400 [
self _setRepresentedObject:target];
404 - (void)replaceObjectAtIndex:(CPUInteger)anIndex withObject:(
id)anObject
409 - (void)replaceObjectsAtIndexes:(
CPIndexSet)theIndexes withObjects:(CPArray)theObjects
412 return _replaceMany(_proxyObject, _replaceManySEL, theIndexes, theObjects);
420 _replace(_proxyObject, _replaceSEL, index, [theObjects objectAtIndex:i++]);
426 var target = [[
self _representedObject] copy];
427 [target replaceObjectsAtIndexes:theIndexes withObjects:theObjects];
428 [
self _setRepresentedObject:target];
441 if (aKey.charAt(0) ===
"@")
443 if (aKey.indexOf(
".") !== -1)
446 if (aKey ===
"@count")
449 return [
self valueForUndefinedKey:aKey];
454 enumerator = [
self objectEnumerator],
457 while ((
object = [enumerator nextObject]) !== nil)
459 var value = [object valueForKey:aKey];
461 if (value === nil || value === undefined)
464 newArray.push(value);
474 [
self valueForUndefinedKey:@"<empty path>"];
476 if (aKeyPath.charAt(0) ===
"@")
478 var dotIndex = aKeyPath.indexOf(
"."),
484 operator = aKeyPath.substring(1, dotIndex);
485 parameter = aKeyPath.substring(dotIndex + 1);
488 operator = aKeyPath.substring(1);
490 return [_CPCollectionKVCOperator performOperation:operator withCollection:self propertyPath:parameter];
495 enumerator = [
self objectEnumerator],
498 while ((
object = [enumerator nextObject]) !== nil)
500 var value = [object valueForKeyPath:aKeyPath];
502 if (value === nil || value === undefined)
505 newArray.push(value);
514 var enumerator = [
self objectEnumerator],
517 while ((
object = [enumerator nextObject]) !== nil)
518 [object setValue:aValue forKey:aKey];
521 - (void)setValue:(
id)aValue forKeyPath:(
CPString)aKeyPath
523 var enumerator = [
self objectEnumerator],
526 while ((
object = [enumerator nextObject]) !== nil)
527 [object setValue:aValue forKeyPath:aKeyPath];
541 - (void)addObserver:(
id)anObserver forKeyPath:(
CPString)aKeyPath options:(CPKeyValueObservingOptions)anOptions context:(
id)aContext
543 if (aKeyPath !==
@"@count")
544 [
CPException raise:CPInvalidArgumentException
reason:"[CPArray " + CPStringFromSelector(_cmd) + "] is not supported. Key path: " + aKeyPath];
554 - (void)removeObserver:(
id)anObserver forKeyPath:(
CPString)aKeyPath
556 if (aKeyPath !==
@"@count")
557 [
CPException raise:CPInvalidArgumentException
reason:"[CPArray " + CPStringFromSelector(_cmd) + "] is not supported. Key path: " + aKeyPath];
563 - (void)addObserver:(
id)anObserver toObjectsAtIndexes:(
CPIndexSet)indexes forKeyPath:(
CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(
id)context
569 [
self[index] addObserver:anObserver forKeyPath:aKeyPath options:options context:context];
578 - (void)removeObserver:(
id)anObserver fromObjectsAtIndexes:(
CPIndexSet)indexes forKeyPath:(
CPString)aKeyPath
584 [
self[index] removeObserver:anObserver forKeyPath:aKeyPath];
Used to implement exception handling (creating & raising).
An object representation of nil.
CPInteger getIndexes:maxCount:inIndexRange:(CPArray anArray, [maxCount] CPInteger aMaxCount, [inIndexRange] CPRange aRange)
void raise:reason:(CPString aName, [reason] CPString aReason)
A collection of unique integers.
CPInvalidArgumentException
id mutableArrayValueForKey:(id aKey)
An immutable string (collection of characters).
if(CPFeatureIsCompatible(CPHTMLCanvasFeature))
CPInteger indexGreaterThanIndex:(CPInteger anIndex)
function CPIntersectionRange(lhsRange, rhsRange)
id valueForKeyPath:(CPString aKeyPath)
CPInteger indexLessThanIndex:(CPInteger anIndex)
id indexSetWithIndexesInRange:(CPRange aRange)
id indexSetWithIndex:(int anIndex)
CPRange function CPMakeRange(location, length)