API  0.9.6
 All Classes Files Functions Variables Macros Groups Pages
CPSet.j
Go to the documentation of this file.
1 /*
2  * CPSet.j
3  * Foundation
4  *
5  * Created by Bailey Carlson
6  * Extended by Ross Boucher
7  * Extended by Nabil Elisa
8  * Rewritten by Francisco Tolmasky
9  * Copyright 2008, 280 North, Inc.
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24  *
25  */
26 
27 
35 @implementation CPSet : CPObject
36 {
37  id __doxygen__;
38 }
39 
40 + (id)alloc
41 {
42  if (self === [CPSet class] || self === [CPMutableSet class])
43  return [_CPPlaceholderSet alloc];
44 
45  return [super alloc];
46 }
47 
51 + (id)set
52 {
53  return [[self alloc] init];
54 }
55 
60 + (id)setWithArray:(CPArray)anArray
61 {
62  return [[self alloc] initWithArray:anArray];
63 }
64 
69 + (id)setWithObject:(id)anObject
70 {
71  return [[self alloc] initWithObjects:anObject];
72 }
73 
79 + (id)setWithObjects:(id)objects count:(CPUInteger)count
80 {
81  return [[self alloc] initWithObjects:objects count:count];
82 }
83 
89 + (id)setWithObjects:(id)anObject, ...
90 {
91  var argumentsArray = Array.prototype.slice.apply(arguments);
92 
93  argumentsArray[0] = [self alloc];
94  argumentsArray[1] = @selector(initWithObjects:);
95 
96  return objj_msgSend.apply(this, argumentsArray);
97 }
98 
103 + (id)setWithSet:(CPSet)set
104 {
105  return [[self alloc] initWithSet:set];
106 }
107 
112 - (id)setByAddingObject:(id)anObject
113 {
114  return [[self class] setWithArray:[[self allObjects] arrayByAddingObject:anObject]];
115 }
116 
121 - (id)setByAddingObjectsFromSet:(CPSet)aSet
122 {
123  return [self setByAddingObjectsFromArray:[aSet allObjects]];
124 }
125 
130 - (id)setByAddingObjectsFromArray:(CPArray)anArray
131 {
132  return [[self class] setWithArray:[[self allObjects] arrayByAddingObjectsFromArray:anArray]];
133 }
134 
138 - (id)init
139 {
140  return [self initWithObjects:nil count:0];
141 }
142 
147 - (id)initWithArray:(CPArray)anArray
148 {
149  return [self initWithObjects:anArray count:[anArray count]];
150 }
151 
157 - (id)initWithObjects:(id)anObject, ...
158 {
159  var index = 2,
160  count = arguments.length;
161 
162  for (; index < count; ++index)
163  if (arguments[index] === nil)
164  break;
165 
166  return [self initWithObjects:Array.prototype.slice.call(arguments, 2, index) count:index - 2];
167 }
168 
174 - (id)initWithObjects:(CPArray)objects count:(CPUInteger)aCount
175 {
176  if (self === _CPSharedPlaceholderSet)
177  return [[_CPConcreteMutableSet alloc] initWithObjects:objects count:aCount];
178 
179  return [super init];
180 }
181 
186 - (id)initWithSet:(CPSet)aSet
187 {
188  return [self initWithArray:[aSet allObjects]];
189 }
190 
196 - (id)initWithSet:(CPSet)aSet copyItems:(BOOL)shouldCopyItems
197 {
198  if (shouldCopyItems)
199  return [aSet valueForKey:@"copy"];
200 
201  return [self initWithSet:aSet];
202 }
203 
207 - (CPUInteger)count
208 {
209  _CPRaiseInvalidAbstractInvocation(self, _cmd);
210 }
211 
215 - (CPArray)allObjects
216 {
217  var objects = [],
218  object,
219  objectEnumerator = [self objectEnumerator];
220 
221  while ((object = [objectEnumerator nextObject]) !== nil)
222  objects.push(object);
223 
224  return objects;
225 }
226 
230 - (id)anyObject
231 {
232  return [[self objectEnumerator] nextObject];
233 }
234 
239 - (BOOL)containsObject:(id)anObject
240 {
241  return [self member:anObject] !== nil;
242 }
243 
248 - (CPSet)filteredSetUsingPredicate:(CPPredicate)aPredicate
249 {
250  var objects = [],
251  object,
252  objectEnumerator = [self objectEnumerator];
253 
254  while ((object = [objectEnumerator nextObject]) !== nil)
255  if ([aPredicate evaluateWithObject:object])
256  objects.push(object);
257 
258  return [[[self class] alloc] initWithArray:objects];
259 }
260 
265 - (void)makeObjectsPerformSelector:(SEL)aSelector
266 {
267  [self makeObjectsPerformSelector:aSelector withObjects:nil];
268 }
269 
275 - (void)makeObjectsPerformSelector:(SEL)aSelector withObject:(id)anObject
276 {
277  [self makeObjectsPerformSelector:aSelector withObjects:[anObject]];
278 }
279 
285 - (void)makeObjectsPerformSelector:(SEL)aSelector withObjects:(CPArray)objects
286 {
287  var object,
288  objectEnumerator = [self objectEnumerator],
289  argumentsArray = [nil, aSelector].concat(objects || []);
290 
291  while ((object = [objectEnumerator nextObject]) !== nil)
292  {
293  argumentsArray[0] = object;
294  objj_msgSend.apply(this, argumentsArray);
295  }
296 }
297 
302 - (id)member:(id)anObject
303 {
304  _CPRaiseInvalidAbstractInvocation(self, _cmd);
305 }
306 
310 - (CPEnumerator)objectEnumerator
311 {
312  _CPRaiseInvalidAbstractInvocation(self, _cmd);
313 }
314 
319 - (void)enumerateObjectsUsingBlock:(Function)aFunction
320 {
321  var object,
322  objectEnumerator = [self objectEnumerator];
323 
324  while ((object = [objectEnumerator nextObject]) !== nil)
325  if (aFunction(object))
326  break;
327 }
328 
329 // FIXME: stop is broken.
330 - (CPSet)objectsPassingTest:(Function)aFunction
331 {
332  var objects = [],
333  object = nil,
334  objectEnumerator = [self objectEnumerator];
335 
336  while ((object = [objectEnumerator nextObject]) !== nil)
337  if (aFunction(object))
338  objects.push(object);
339 
340  return [[[self class] alloc] initWithArray:objects];
341 }
342 
347 - (BOOL)isSubsetOfSet:(CPSet)aSet
348 {
349  var object = nil,
350  objectEnumerator = [self objectEnumerator];
351 
352  while ((object = [objectEnumerator nextObject]) !== nil)
353  if (![aSet containsObject:object])
354  return NO;
355 
356  return YES;
357 }
358 
363 - (BOOL)intersectsSet:(CPSet)aSet
364 {
365  if (self === aSet)
366  // The empty set intersects nothing
367  return [self count] > 0;
368 
369  var object = nil,
370  objectEnumerator = [self objectEnumerator];
371 
372  while ((object = [objectEnumerator nextObject]) !== nil)
373  if ([aSet containsObject:object])
374  return YES;
375 
376  return NO;
377 }
378 
384 - (CPArray)sortedArrayUsingDescriptors:(CPArray)someSortDescriptors
385 {
386  return [[self allObjects] sortedArrayUsingDescriptors:someSortDescriptors];
387 }
388 
393 - (BOOL)isEqualToSet:(CPSet)aSet
394 {
395  return [self isEqual:aSet];
396 }
397 
402 - (BOOL)isEqual:(CPSet)aSet
403 {
404  // If both are subsets of each other, they are equal
405  return self === aSet ||
406  [aSet isKindOfClass:[CPSet class]] &&
407  ([self count] === [aSet count] &&
408  [aSet isSubsetOfSet:self]);
409 }
410 
411 - (CPString)description
412 {
413  var string = "{(\n",
414  objects = [self allObjects],
415  index = 0,
416  count = [objects count];
417 
418  for (; index < count; ++index)
419  {
420  var object = objects[index];
421 
422  string += "\t" + String(object).split('\n').join("\n\t") + "\n";
423  }
424 
425  return string + ")}";
426 }
427 
428 @end
429 
430 @implementation CPSet (CPCopying)
431 
432 - (id)copy
433 {
434  return [[self class] setWithSet:self];
435 }
436 
437 - (id)mutableCopy
438 {
439  return [self copy];
440 }
441 
442 @end
443 
444 var CPSetObjectsKey = @"CPSetObjectsKey";
445 
446 @implementation CPSet (CPCoding)
447 
448 - (id)initWithCoder:(CPCoder)aCoder
449 {
450  return [self initWithArray:[aCoder decodeObjectForKey:CPSetObjectsKey]];
451 }
452 
453 - (void)encodeWithCoder:(CPCoder)aCoder
454 {
455  [aCoder encodeObject:[self allObjects] forKey:CPSetObjectsKey];
456 }
457 
458 @end
459 
461 
462 - (id)valueForKey:(CPString)aKey
463 {
464  if (aKey === "@count")
465  return [self count];
466 
467  var valueSet = [CPSet set],
468  object,
469  objectEnumerator = [self objectEnumerator];
470 
471  while ((object = [objectEnumerator nextObject]) !== nil)
472  {
473  var value = [object valueForKey:aKey];
474 
475  [valueSet addObject:value];
476  }
477 
478  return valueSet;
479 }
480 
481 - (void)setValue:(id)aValue forKey:(CPString)aKey
482 {
483  var object,
484  objectEnumerator = [self objectEnumerator];
485 
486  while ((object = [objectEnumerator nextObject]) !== nil)
487  [object setValue:aValue forKey:aKey];
488 }
489 
490 @end
491 
492 var _CPSharedPlaceholderSet = nil;
493 @implementation _CPPlaceholderSet : CPSet
494 {
495  id __doxygen__;
496 }
497 
498 + (id)alloc
499 {
500  if (!_CPSharedPlaceholderSet)
501  _CPSharedPlaceholderSet = [super alloc];
502 
503  return _CPSharedPlaceholderSet;
504 }
505 
506 @end
507 
508 // This will be correctly solved when we move to true immutable/mutable pairs.