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