API  1.0.0
CPMutableArray.j
Go to the documentation of this file.
1 
2 
3 
11 @implementation CPMutableArray : CPArray
12 {
13  id __doxygen__;
14 }
15 
16 // Creating arrays
22 + (CPArray)arrayWithCapacity:(CPUInteger)aCapacity
23 {
24  return [[self alloc] initWithCapacity:aCapacity];
25 }
26 
31 /*- (id)initWithCapacity:(CPUInteger)aCapacity
32 {
33  return self;
34 }*/
35 
36 // Adding and replacing objects
41 - (void)addObject:(id)anObject
42 {
43  _CPRaiseInvalidAbstractInvocation(self, _cmd);
44 }
45 
50 - (void)addObjectsFromArray:(CPArray)anArray
51 {
52  var index = 0,
53  count = [anArray count];
54 
55  for (; index < count; ++index)
56  [self addObject:[anArray objectAtIndex:index]];
57 }
58 
64 - (void)insertObject:(id)anObject atIndex:(CPUInteger)anIndex
65 {
66  _CPRaiseInvalidAbstractInvocation(self, _cmd);
67 }
68 
74 - (void)insertObjects:(CPArray)objects atIndexes:(CPIndexSet)indexes
75 {
76  var indexesCount = [indexes count],
77  objectsCount = [objects count];
78 
79  if (indexesCount !== objectsCount)
80  [CPException raise:CPRangeException reason:"the counts of the passed-in array (" + objectsCount + ") and index set (" + indexesCount + ") must be identical."];
81 
82  var lastIndex = [indexes lastIndex];
83 
84  if (lastIndex >= [self count] + indexesCount)
85  [CPException raise:CPRangeException reason:"the last index (" + lastIndex + ") must be less than the sum of the original count (" + [self count] + ") and the insertion count (" + indexesCount + ")."];
86 
87  var index = 0,
88  currentIndex = [indexes firstIndex];
89 
90  for (; index < objectsCount; ++index, currentIndex = [indexes indexGreaterThanIndex:currentIndex])
91  [self insertObject:[objects objectAtIndex:index] atIndex:currentIndex];
92 }
93 
94 - (CPUInteger)insertObject:(id)anObject inArraySortedByDescriptors:(CPArray)descriptors
95 {
96  var index,
97  count = [descriptors count];
98 
99  if (count)
100  index = [self indexOfObject:anObject
101  inSortedRange:nil
102  options:CPBinarySearchingInsertionIndex
103  usingComparator:function(lhs, rhs)
104  {
105  var index = 0,
106  result = CPOrderedSame;
107 
108  while (index < count && ((result = [[descriptors objectAtIndex:index] compareObject:lhs withObject:rhs]) === CPOrderedSame))
109  ++index;
110 
111  return result;
112  }];
113 
114  else
115  index = [self count];
116 
117  [self insertObject:anObject atIndex:index];
118 
119  return index;
120 }
121 
127 - (void)replaceObjectAtIndex:(CPUInteger)anIndex withObject:(id)anObject
128 {
129  _CPRaiseInvalidAbstractInvocation(self, _cmd);
130 }
131 
138 - (void)replaceObjectsAtIndexes:(CPIndexSet)indexes withObjects:(CPArray)objects
139 {
140  var i = 0,
141  index = [indexes firstIndex];
142 
143  while (index !== CPNotFound)
144  {
145  [self replaceObjectAtIndex:index withObject:[objects objectAtIndex:i++]];
146  index = [indexes indexGreaterThanIndex:index];
147  }
148 }
149 
158 - (void)replaceObjectsInRange:(CPRange)aRange withObjectsFromArray:(CPArray)anArray range:(CPRange)otherRange
159 {
160  [self removeObjectsInRange:aRange];
161 
162  if (otherRange && (otherRange.location !== 0 || otherRange.length !== [anArray count]))
163  anArray = [anArray subarrayWithRange:otherRange];
164 
165  var indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(aRange.location, [anArray count])];
166 
167  [self insertObjects:anArray atIndexes:indexes];
168 }
169 
177 - (void)replaceObjectsInRange:(CPRange)aRange withObjectsFromArray:(CPArray)anArray
178 {
179  [self replaceObjectsInRange:aRange withObjectsFromArray:anArray range:nil];
180 }
181 
186 - (void)setArray:(CPArray)anArray
187 {
188  if (self === anArray)
189  return;
190 
191  [self removeAllObjects];
192  [self addObjectsFromArray:anArray];
193 }
194 
195 // Removing Objects
199 - (void)removeAllObjects
200 {
201  while ([self count])
202  [self removeLastObject];
203 }
204 
208 - (void)removeLastObject
209 {
210  _CPRaiseInvalidAbstractInvocation(self, _cmd);
211 }
212 
217 - (void)removeObject:(id)anObject
218 {
219  [self removeObject:anObject inRange:CPMakeRange(0, [self count])];
220 }
221 
227 - (void)removeObject:(id)anObject inRange:(CPRange)aRange
228 {
229  var index;
230 
231  while ((index = [self indexOfObject:anObject inRange:aRange]) != CPNotFound)
232  {
233  [self removeObjectAtIndex:index];
234  aRange = CPIntersectionRange(CPMakeRange(index, [self count] - index), aRange);
235  }
236 }
237 
242 - (void)removeObjectAtIndex:(CPUInteger)anIndex
243 {
244  _CPRaiseInvalidAbstractInvocation(self, _cmd);
245 }
246 
251 - (void)removeObjectsAtIndexes:(CPIndexSet)anIndexSet
252 {
253  var index = [anIndexSet lastIndex];
254 
255  while (index !== CPNotFound)
256  {
257  [self removeObjectAtIndex:index];
258  index = [anIndexSet indexLessThanIndex:index];
259  }
260 }
261 
267 - (void)removeObjectIdenticalTo:(id)anObject
268 {
269  [self removeObjectIdenticalTo:anObject inRange:CPMakeRange(0, [self count])];
270 }
271 
279 - (void)removeObjectIdenticalTo:(id)anObject inRange:(CPRange)aRange
280 {
281  var index,
282  count = [self count];
283 
284  while ((index = [self indexOfObjectIdenticalTo:anObject inRange:aRange]) !== CPNotFound)
285  {
286  [self removeObjectAtIndex:index];
287  aRange = CPIntersectionRange(CPMakeRange(index, (--count) - index), aRange);
288  }
289 }
290 
295 - (void)removeObjectsInArray:(CPArray)anArray
296 {
297  var index = 0,
298  count = [anArray count];
299 
300  for (; index < count; ++index)
301  [self removeObject:[anArray objectAtIndex:index]];
302 }
303 
308 - (void)removeObjectsInRange:(CPRange)aRange
309 {
310  var index = aRange.location,
311  count = CPMaxRange(aRange);
312 
313  while (count-- > index)
314  [self removeObjectAtIndex:index];
315 }
316 
317 // Rearranging objects
323 - (void)exchangeObjectAtIndex:(CPUInteger)anIndex withObjectAtIndex:(CPUInteger)otherIndex
324 {
325  if (anIndex === otherIndex)
326  return;
327 
328  var temporary = [self objectAtIndex:anIndex];
329 
330  [self replaceObjectAtIndex:anIndex withObject:[self objectAtIndex:otherIndex]];
331  [self replaceObjectAtIndex:otherIndex withObject:temporary];
332 }
333 
334 - (void)sortUsingDescriptors:(CPArray)descriptors
335 {
336  var i = [descriptors count],
337  jsDescriptors = [];
338 
339  // Revert the order of the descriptors
340  while (i--)
341  {
342  var d = [descriptors objectAtIndex:i];
343  [jsDescriptors addObject:{ "k": [d key], "a": [d ascending], "s": [d selector]}];
344  }
345  sortArrayUsingJSDescriptors(self, jsDescriptors);
346 }
347 
353 - (void)sortUsingFunction:(Function)aFunction context:(id)aContext
354 {
355  sortArrayUsingFunction(self, aFunction, aContext);
356 }
357 
362 - (void)sortUsingSelector:(SEL)aSelector
363 {
364  sortArrayUsingFunction(self, selectorCompare, aSelector);
365 }
366 
367 @end
368 
370 
371 - (id)mutableCopy
372 {
373  var r = [CPMutableArray new];
374  [r addObjectsFromArray:self];
375  return r;
376 }
377 
378 @end
379 
380 var selectorCompare = function(object1, object2, selector)
381 {
382  return [object1 performSelector:selector withObject:object2];
383 };
384 
385 var sortArrayUsingFunction = function(array, aFunction, aContext)
386 {
387  var h,
388  i,
389  j,
390  k,
391  l,
392  m,
393  n = array.length,
394  o;
395 
396  var A,
397  B = [];
398 
399  for (h = 1; h < n; h += h)
400  {
401  for (m = n - 1 - h; m >= 0; m -= h + h)
402  {
403  l = m - h + 1;
404  if (l < 0)
405  l = 0;
406 
407  for (i = 0, j = l; j <= m; i++, j++)
408  B[i] = array[j];
409 
410  for (i = 0, k = l; k < j && j <= m + h; k++)
411  {
412  A = array[j];
413  o = aFunction(A, B[i], aContext);
414 
415  if (o >= 0)
416  array[k] = B[i++];
417  else
418  {
419  array[k] = A;
420  j++;
421  }
422  }
423 
424  while (k < j)
425  array[k++] = B[i++];
426  }
427  }
428 }
429 
430 // This is for speed
431 var CPMutableArrayNull = [CPNull null];
432 
433 // Observe that the sort descriptors has the reversed order by the caller
434 var sortArrayUsingJSDescriptors = function(a, d)
435 {
436  var h,
437  i,
438  j,
439  k,
440  l,
441  m,
442  n = a.length,
443  dl = d.length - 1,
444  o,
445  c = {};
446 
447  var A,
448  B = [],
449  C1,
450  C2,
451  cn,
452  aUID,
453  bUID,
454  key,
455  dd,
456  value1,
457  value2,
458  cpNull = CPMutableArrayNull;
459 
460  if (dl < 0)
461  return;
462 
463  for (h = 1; h < n; h += h)
464  {
465  for (m = n - 1 - h; m >= 0; m -= h + h)
466  {
467  l = m - h + 1;
468 
469  if (l < 0)
470  l = 0;
471 
472  for (i = 0, j = l; j <= m; i++, j++)
473  B[i] = a[j];
474 
475  for (i = 0, k = l; k < j && j <= m + h; k++)
476  {
477  A = a[j];
478  aUID = A._UID;
479 
480  if (!aUID)
481  aUID = [A UID];
482 
483  C1 = c[aUID];
484 
485  if (!C1)
486  {
487  C1 = {};
488  cn = dl;
489 
490  do
491  {
492  key = d[cn].k;
493  C1[key] = [A valueForKeyPath:key];
494  } while (cn--)
495 
496  c[aUID] = C1;
497  }
498 
499  bUID = B[i]._UID;
500 
501  if (!bUID)
502  bUID = [B[i] UID];
503 
504  C2 = c[bUID];
505 
506  if (!C2)
507  {
508  C2 = {};
509  cn = dl;
510 
511  do
512  {
513  key = d[cn].k;
514  C2[key] = [B[i] valueForKeyPath:key];
515  } while (cn--)
516 
517  c[bUID] = C2;
518  }
519 
520  cn = dl;
521 
522  do
523  {
524  dd = d[cn];
525  key = dd.k;
526  value1 = C1[key];
527  value2 = C2[key];
528  if (value1 === nil || value1 === cpNull)
529  o = value2 === nil || value2 === cpNull ? CPOrderedSame : CPOrderedAscending;
530  else
531  o = value2 === nil || value2 === cpNull ? CPOrderedDescending : value1.isa.objj_msgSend1(value1, dd.s, value2);
532 
533  if (o && !dd.a)
534  o = -o;
535  } while (cn-- && o == CPOrderedSame)
536 
537  if (o >= 0)
538  a[k] = B[i++];
539  else
540  {
541  a[k] = A;
542  j++;
543  }
544  }
545 
546  while (k < j)
547  a[k++] = B[i++];
548  }
549  }
550 }
void addObjectsFromArray:(CPArray anArray)
Used to implement exception handling (creating & raising).
Definition: CPException.h:2
CPOrderedAscending
Definition: CPObjJRuntime.j:48
void insertObjects:atIndexes:(CPArray objects, [atIndexes] CPIndexSet indexes)
CPInteger lastIndex()
Definition: CPIndexSet.j:289
An object representation of nil.
Definition: CPNull.h:2
CPOrderedSame
Definition: CPObjJRuntime.j:54
void removeObjectIdenticalTo:inRange:(id anObject, [inRange] CPRange aRange)
void raise:reason:(CPString aName, [reason] CPString aReason)
Definition: CPException.j:66
A collection of unique integers.
Definition: CPIndexSet.h:2
CPInteger firstIndex()
Definition: CPIndexSet.j:278
var selectorCompare
void removeObjectsInRange:(CPRange aRange)
function CPMaxRange(aRange)
Definition: CPRange.j:70
CPNull null()
Definition: CPNull.j:51
CPInteger indexGreaterThanIndex:(CPInteger anIndex)
Definition: CPIndexSet.j:301
void replaceObjectAtIndex:withObject:(CPUInteger anIndex, [withObject] id anObject)
CPOrderedDescending
Definition: CPObjJRuntime.j:60
var sortArrayUsingFunction
function CPIntersectionRange(lhsRange, rhsRange)
Definition: CPRange.j:120
void removeObject:inRange:(id anObject, [inRange] CPRange aRange)
void replaceObjectsInRange:withObjectsFromArray:range:(CPRange aRange, [withObjectsFromArray] CPArray anArray, [range] CPRange otherRange)
void insertObject:atIndex:(id anObject, [atIndex] CPUInteger anIndex)
void removeObjectAtIndex:(CPUInteger anIndex)
CPNotFound
Definition: CPObjJRuntime.j:62
CPInteger indexLessThanIndex:(CPInteger anIndex)
Definition: CPIndexSet.j:332
id indexSetWithIndexesInRange:(CPRange aRange)
Definition: CPIndexSet.j:60
CPRange function CPMakeRange(location, length)
Definition: CPRange.j:37