API 0.9.5
Foundation/CPSet/CPSet.j
Go to the documentation of this file.
00001 /*
00002  * CPSet.j
00003  * Foundation
00004  *
00005  * Created by Bailey Carlson
00006  * Extended by Ross Boucher
00007  * Extended by Nabil Elisa
00008  * Rewritten by Francisco Tolmasky
00009  * Copyright 2008, 280 North, Inc.
00010  *
00011  * This library is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU Lesser General Public
00013  * License as published by the Free Software Foundation; either
00014  * version 2.1 of the License, or (at your option) any later version.
00015  *
00016  * This library is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00019  * Lesser General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Lesser General Public
00022  * License along with this library; if not, write to the Free Software
00023  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00024  *
00025  */
00026 @implementation CPSet : CPObject
00027 {
00028     id __doxygen__;
00029 }
00030 
00031 + (id)alloc
00032 {
00033     if (self === [CPSet class] || self === [CPMutableSet class])
00034         return [_CPPlaceholderSet alloc];
00035 
00036     return [super alloc];
00037 }
00038 
00039 /*
00040     Creates and returns an empty set.
00041 */
00042 + (id)set
00043 {
00044     return [[self alloc] init];
00045 }
00046 
00047 /*
00048     Creates and returns a set containing a uniqued collection of those objects contained in a given array.
00049     @param anArray array containing the objects to add to the new set. If the same object appears more than once objects, it is added only once to the returned set.
00050 */
00051 + (id)setWithArray:(CPArray)anArray
00052 {
00053     return [[self alloc] initWithArray:anArray];
00054 }
00055 
00056 /*
00057     Creates and returns a set that contains a single given object.
00058     @param anObject The object to add to the new set.
00059 */
00060 + (id)setWithObject:(id)anObject
00061 {
00062     return [[self alloc] initWithObjects:anObject];
00063 }
00064 
00065 /*
00066     Creates and returns a set containing a specified number of objects from a given array of objects.
00067     @param objects A array of objects to add to the new set. If the same object appears more than once objects, it is added only once to the returned set.
00068     @param count The number of objects from objects to add to the new set.
00069 */
00070 + (id)setWithObjects:(id)objects count:(CPUInteger)count
00071 {
00072     return [[self alloc] initWithObjects:objects count:count];
00073 }
00074 
00075 /*
00076     Creates and returns a set containing the objects in a given argument list.
00077     @param anObject The first object to add to the new set.
00078     @param ... A comma-separated list of objects, ending with nil, to add to the new set. If the same object appears more than once objects, it is added only once to the returned set.
00079 */
00080 + (id)setWithObjects:(id)anObject, ...
00081 {
00082     var argumentsArray = Array.prototype.slice.apply(arguments);
00083 
00084     argumentsArray[0] = [self alloc];
00085     argumentsArray[1] = @selector(initWithObjects:);
00086 
00087     return objj_msgSend.apply(this, argumentsArray);
00088 }
00089 
00090 /*
00091     Creates and returns a set containing the objects from another set.
00092     @param aSet A set containing the objects to add to the new set.
00093 */
00094 + (id)setWithSet:(CPSet)set
00095 {
00096     return [[self alloc] initWithSet:set];
00097 }
00098 
00099 - (id)setByAddingObject:(id)anObject
00100 {
00101     return [[self class] setWithArray:[[self allObjects] arrayByAddingObject:anObject]];
00102 }
00103 
00104 - (id)setByAddingObjectsFromSet:(CPSet)aSet
00105 {
00106     return [self setByAddingObjectsFromArray:[aSet allObjects]];
00107 }
00108 
00109 - (id)setByAddingObjectsFromArray:(CPArray)anArray
00110 {
00111     return [[self class] setWithArray:[[self allObjects] arrayByAddingObjectsFromArray:anArray]];
00112 }
00113 
00114 /*
00115     Basic initializer, returns an empty set
00116 */
00117 - (id)init
00118 {
00119     return [self initWithObjects:nil count:0];
00120 }
00121 
00122 /*
00123     Initializes a newly allocated set with the objects that are contained in a given array.
00124     @param array An array of objects to add to the new set. If the same object appears more than once in array, it is represented only once in the returned set.
00125 */
00126 - (id)initWithArray:(CPArray)anArray
00127 {
00128     return [self initWithObjects:anArray count:[anArray count]];
00129 }
00130 
00131 /*
00132     Initializes a newly allocated set with members taken from the specified list of objects.
00133     @param anObject The first object to add to the new set.
00134     @param ... A comma-separated list of objects, ending with nil, to add to the new set. If the same object appears more than once in the list, it is represented only once in the returned set.
00135 */
00136 - (id)initWithObjects:(id)anObject, ...
00137 {
00138     var index = 2,
00139         count = arguments.length;
00140 
00141     for (; index < count; ++index)
00142         if (arguments[index] === nil)
00143             break;
00144 
00145     return [self initWithObjects:Array.prototype.slice.call(arguments, 2, index) count:index - 2];
00146 }
00147 
00148 - (id)initWithObjects:(CPArray)objects count:(CPUInteger)aCount
00149 {
00150     if (self === _CPSharedPlaceholderSet)
00151         return [[_CPConcreteMutableSet alloc] initWithObjects:objects count:aCount];
00152 
00153     return [super init];
00154 }
00155 
00156 /*
00157     Initializes a newly allocated set and adds to it objects from another given set.
00158 */
00159 - (id)initWithSet:(CPSet)aSet
00160 {
00161     return [self initWithArray:[aSet allObjects]];
00162 }
00163 
00164 /*
00165     Initializes a newly allocated set and adds to it members of another given set. Only included for compatability.
00166 */
00167 - (id)initWithSet:(CPSet)aSet copyItems:(BOOL)shouldCopyItems
00168 {
00169     if (shouldCopyItems)
00170         return [aSet valueForKey:@"copy"];
00171 
00172     return [self initWithSet:aSet];
00173 }
00174 
00175 /*
00176     Returns the number of members in the receiver.
00177 */
00178 - (CPUInteger)count
00179 {
00180     _CPRaiseInvalidAbstractInvocation(self, _cmd);
00181 }
00182 
00183 /*
00184     Returns an array containing the receiver’s members, or an empty array if the receiver has no members.
00185 */
00186 - (CPArray)allObjects
00187 {
00188     var objects = [],
00189         object,
00190         objectEnumerator = [self objectEnumerator];
00191 
00192     while ((object = [objectEnumerator nextObject]) !== nil)
00193         objects.push(object);
00194 
00195     return objects;
00196 }
00197 
00198 /*
00199     Returns one of the objects in the receiver, or nil if the receiver contains no objects.
00200 */
00201 - (id)anyObject
00202 {
00203     return [[self objectEnumerator] nextObject];
00204 }
00205 
00206 /*
00207     Returns a Boolean value that indicates whether a given object is present in the receiver.
00208     @param anObject The object for which to test membership of the receiver.
00209 */
00210 - (BOOL)containsObject:(id)anObject
00211 {
00212     return [self member:anObject] !== nil;
00213 }
00214 
00215 - (void)filteredSetUsingPredicate:(CPPredicate)aPredicate
00216 {
00217     var objects = [],
00218         object,
00219         objectEnumerator = [self objectEnumerator];
00220 
00221     while ((object = [objectEnumerator nextObject]) !== nil)
00222         if ([aPredicate evaluateWithObject:object])
00223             objects.push(object);
00224 
00225     return [[[self class] alloc] initWithArray:objects];
00226 }
00227 
00228 /*
00229     Sends to each object in the receiver a message specified by a given selector.
00230     @param aSelector A selector that specifies the message to send to the members of the receiver. The method must not take any arguments. It should not have the side effect of modifying the receiver. This value must not be NULL.
00231 */
00232 - (void)makeObjectsPerformSelector:(SEL)aSelector
00233 {
00234     [self makeObjectsPerformSelector:aSelector withObjects:nil];
00235 }
00236 
00237 /*
00238     Sends to each object in the receiver a message specified by a given selector.
00239     @param aSelector A selector that specifies the message to send to the receiver's members. The method must take a single argument of type id. The method should not, as a side effect, modify the receiver. The value must not be NULL.
00240     @param anObject The object to pass as an argument to the method specified by aSelector.
00241 */
00242 - (void)makeObjectsPerformSelector:(SEL)aSelector withObject:(id)anObject
00243 {
00244     [self makeObjectsPerformSelector:aSelector withObjects:[anObject]];
00245 }
00246 
00247 /*
00248     Sends to each object in the receiver a message specified by a given selector.
00249     @param aSelector A selector that specifies the message to send to the receiver's members. The method must take a single argument of type id. The method should not, as a side effect, modify the receiver. The value must not be NULL.
00250     @param objects The objects to pass as an argument to the method specified by aSelector.
00251 */
00252 - (void)makeObjectsPerformSelector:(SEL)aSelector withObjects:(CPArray)objects
00253 {
00254     var object,
00255         objectEnumerator = [self objectEnumerator],
00256         argumentsArray = [nil, aSelector].concat(objects || []);
00257 
00258     while ((object = [objectEnumerator nextObject]) !== nil)
00259     {
00260         argumentsArray[0] = object;
00261         objj_msgSend.apply(this, argumentsArray);
00262     }
00263 }
00264 
00265 /*
00266     Determines whether the receiver contains an object equal to a given object, and returns that object if it is present.
00267     @param anObject The object for which to test for membership of the receiver.
00268 */
00269 - (id)member:(id)anObject
00270 {
00271     _CPRaiseInvalidAbstractInvocation(self, _cmd);
00272 }
00273 
00274 - (CPEnumerator)objectEnumerator
00275 {
00276     _CPRaiseInvalidAbstractInvocation(self, _cmd);
00277 }
00278 
00279 - (void)enumerateObjectsUsingBlock:(Function)aFunction
00280 {
00281     var object,
00282         objectEnumerator = [self objectEnumerator];
00283 
00284     while ((object = [objectEnumerator nextObject]) !== nil)
00285         if (aFunction(object))
00286             break;
00287 }
00288 
00289 // FIXME: stop is broken.
00290 - (CPSet)objectsPassingTest:(Function)aFunction
00291 {
00292     var objects = [],
00293         object = nil,
00294         objectEnumerator = [self objectEnumerator];
00295 
00296     while ((object = [objectEnumerator nextObject]) !== nil)
00297         if (aFunction(object))
00298             objects.push(object);
00299 
00300     return [[[self class] alloc] initWithArray:objects];
00301 }
00302 
00303 /*
00304     Returns a Boolean value that indicates whether every object in the receiver is also present in another given set.
00305     @param set The set with which to compare the receiver.
00306 */
00307 - (BOOL)isSubsetOfSet:(CPSet)aSet
00308 {
00309     var object = nil,
00310         objectEnumerator = [self objectEnumerator];
00311 
00312     while ((object = [objectEnumerator nextObject]) !== nil)
00313         if (![aSet containsObject:object])
00314             return NO;
00315 
00316     return YES;
00317 }
00318 
00319 /*
00320     Returns a Boolean value that indicates whether at least one object in the receiver is also present in another given set.
00321     @param set The set with which to compare the receiver.
00322 */
00323 - (BOOL)intersectsSet:(CPSet)aSet
00324 {
00325     if (self === aSet)
00326         // The empty set intersects nothing
00327         return [self count] > 0;
00328 
00329     var object = nil,
00330         objectEnumerator = [self objectEnumerator];
00331 
00332     while ((object = [objectEnumerator nextObject]) !== nil)
00333         if ([aSet containsObject:object])
00334             return YES;
00335 
00336     return NO;
00337 }
00338 
00339 /*
00340     Compares the receiver to another set.
00341     @param set The set with which to compare the receiver.
00342 */
00343 - (BOOL)isEqualToSet:(CPSet)aSet
00344 {
00345     return [self isEqual:aSet];
00346 }
00347 
00348 - (BOOL)isEqual:(CPSet)aSet
00349 {
00350     // If both are subsets of each other, they are equal
00351     return  self === aSet ||
00352             [aSet isKindOfClass:[CPSet class]] &&
00353             ([self count] === [aSet count] &&
00354             [aSet isSubsetOfSet:self]);
00355 }
00356 
00357 - (CPString)description
00358 {
00359     var string = "{(\n",
00360         objects = [self allObjects],
00361         index = 0,
00362         count = [objects count];
00363 
00364     for (; index < count; ++index)
00365     {
00366         var object = objects[index];
00367 
00368         string += "\t" + String(object).split('\n').join("\n\t") + "\n";
00369     }
00370 
00371     return string + ")}";
00372 }
00373 
00374 @end
00375 
00376 @implementation CPSet (CPCopying)
00377 
00378 - (id)copy
00379 {
00380     return [[self class] setWithSet:self];
00381 }
00382 
00383 - (id)mutableCopy
00384 {
00385     return [self copy];
00386 }
00387 
00388 @end
00389 
00390 var CPSetObjectsKey = @"CPSetObjectsKey";
00391 
00392 @implementation CPSet (CPCoding)
00393 
00394 - (id)initWithCoder:(CPCoder)aCoder
00395 {
00396     return [self initWithArray:[aCoder decodeObjectForKey:CPSetObjectsKey]];
00397 }
00398 
00399 - (void)encodeWithCoder:(CPCoder)aCoder
00400 {
00401     [aCoder encodeObject:[self allObjects] forKey:CPSetObjectsKey];
00402 }
00403 
00404 @end
00405 
00406 @implementation CPSet (CPKeyValueCoding)
00407 
00408 - (id)valueForKey:(CPString)aKey
00409 {
00410     if (aKey === "@count")
00411         return [self count];
00412 
00413     var valueSet = [CPSet set],
00414         object,
00415         objectEnumerator = [self objectEnumerator];
00416 
00417     while ((object = [objectEnumerator nextObject]) !== nil)
00418     {
00419         var value = [object valueForKey:aKey];
00420 
00421         [valueSet addObject:value];
00422     }
00423 
00424     return valueSet;
00425 }
00426 
00427 - (void)setValue:(id)aValue forKey:(CPString)aKey
00428 {
00429     var object,
00430         objectEnumerator = [self objectEnumerator];
00431 
00432     while ((object = [objectEnumerator nextObject]) !== nil)
00433         [object setValue:aValue forKey:aKey];
00434 }
00435 
00436 @end
00437 
00438 var _CPSharedPlaceholderSet   = nil;
00439 @implementation _CPPlaceholderSet : CPSet
00440 {
00441     id __doxygen__;
00442 }
00443 
00444 + (id)alloc
00445 {
00446     if (!_CPSharedPlaceholderSet)
00447         _CPSharedPlaceholderSet = [super alloc];
00448 
00449     return _CPSharedPlaceholderSet;
00450 }
00451 
00452 @end
00453 
00454 // This will be correctly solved when we move to true immutable/mutable pairs.
 All Classes Files Functions Variables Defines