00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 @import "CPArray.j"
00024 @import "CPObject.j"
00025 @import "CPEnumerator.j"
00026 @import "CPException.j"
00027
00028
00029
00030 @implementation _CPDictionaryValueEnumerator : CPEnumerator
00031 {
00032 CPEnumerator _keyEnumerator;
00033 CPDictionary _dictionary;
00034 }
00035
00036 - (id)initWithDictionary:(CPDictionary)aDictionary
00037 {
00038 self = [super init];
00039
00040 if (self)
00041 {
00042 _keyEnumerator = [aDictionary keyEnumerator];
00043 _dictionary = aDictionary;
00044 }
00045
00046 return self;
00047 }
00048
00049 - (id)nextObject
00050 {
00051 var key = [_keyEnumerator nextObject];
00052
00053 if (!key)
00054 return nil;
00055
00056 return [_dictionary objectForKey:key];
00057 }
00058
00059 @end
00060
00078 @implementation CPDictionary : CPObject
00079 {
00080 }
00081
00082
00083
00084
00085 + (id)alloc
00086 {
00087 return new CFMutableDictionary();
00088 }
00089
00093 + (id)dictionary
00094 {
00095 return [[self alloc] init];
00096 }
00097
00103 + (id)dictionaryWithDictionary:(CPDictionary)aDictionary
00104 {
00105 return [[self alloc] initWithDictionary:aDictionary];
00106 }
00107
00114 + (id)dictionaryWithObject:(id)anObject forKey:(id)aKey
00115 {
00116 return [[self alloc] initWithObjects:[anObject] forKeys:[aKey]];
00117 }
00118
00126 + (id)dictionaryWithObjects:(CPArray)objects forKeys:(CPArray)keys
00127 {
00128 return [[self alloc] initWithObjects:objects forKeys:keys];
00129 }
00130
00136 + (id)dictionaryWithJSObject:(JSObject)object
00137 {
00138 return [self dictionaryWithJSObject:object recursively:NO];
00139 }
00140
00146 + (id)dictionaryWithJSObject:(JSObject)object recursively:(BOOL)recursively
00147 {
00148 var dictionary = [[self alloc] init];
00149
00150 for (var key in object)
00151 {
00152 if (!object.hasOwnProperty(key))
00153 continue;
00154
00155 var value = object[key];
00156
00157 if (value === null)
00158 {
00159 [dictionary setObject:[CPNull null] forKey:key];
00160 continue;
00161 }
00162
00163 if (recursively)
00164 {
00165 if (value.constructor === Object)
00166 value = [CPDictionary dictionaryWithJSObject:value recursively:YES];
00167 else if ([value isKindOfClass:CPArray])
00168 {
00169 var newValue = [];
00170 for (var i = 0, count = value.length; i < count; i++)
00171 {
00172 var thisValue = value[i];
00173
00174 if (thisValue.constructor === Object)
00175 newValue.push([CPDictionary dictionaryWithJSObject:thisValue recursively:YES]);
00176 else
00177 newValue.push(thisValue);
00178 }
00179
00180 value = newValue;
00181 }
00182 }
00183
00184 [dictionary setObject:value forKey:key];
00185 }
00186
00187 return dictionary;
00188 }
00189
00207 + (id)dictionaryWithObjectsAndKeys:(id)firstObject, ...
00208 {
00209 arguments[0] = [self alloc];
00210 arguments[1] = @selector(initWithObjectsAndKeys:);
00211
00212 return objj_msgSend.apply(this, arguments);
00213 }
00214
00220 - (id)initWithDictionary:(CPDictionary)aDictionary
00221 {
00222 var key = "",
00223 dictionary = [[CPDictionary alloc] init];
00224
00225 for (key in aDictionary._buckets)
00226 [dictionary setObject:[aDictionary objectForKey:key] forKey:key];
00227
00228 return dictionary;
00229 }
00230
00238 - (id)initWithObjects:(CPArray)objects forKeys:(CPArray)keyArray
00239 {
00240 self = [super init];
00241
00242 if ([objects count] != [keyArray count])
00243 [CPException raise:CPInvalidArgumentException reason:"Counts are different.("+[objects count]+"!="+[keyArray count]+")"];
00244
00245 if (self)
00246 {
00247 var i = [keyArray count];
00248
00249 while (i--)
00250 [self setObject:objects[i] forKey:keyArray[i]];
00251 }
00252
00253 return self;
00254 }
00255
00270 - (id)initWithObjectsAndKeys:(id)firstObject, ...
00271 {
00272 var argCount = arguments.length;
00273
00274 if (argCount % 2 !== 0)
00275 [CPException raise:CPInvalidArgumentException reason:"Key-value count is mismatched. (" + argCount + " arguments passed)"];
00276
00277 self = [super init];
00278
00279 if (self)
00280 {
00281
00282 var index = 2;
00283
00284 for(; index < argCount; index += 2)
00285 {
00286 var value = arguments[index];
00287
00288 if (value === nil)
00289 break;
00290
00291 [self setObject:value forKey:arguments[index + 1]];
00292 }
00293 }
00294
00295 return self;
00296 }
00297
00301 - (CPDictionary)copy
00302 {
00303 return [CPDictionary dictionaryWithDictionary:self];
00304 }
00305
00309 - (int)count
00310 {
00311 return _count;
00312 }
00313
00317 - (CPArray)allKeys
00318 {
00319 return _keys;
00320 }
00321
00325 - (CPArray)allValues
00326 {
00327 var index = _keys.length,
00328 values = [];
00329
00330 while (index--)
00331 values.push(self.valueForKey(_keys[index]));
00332
00333 return values;
00334 }
00335
00339 - (CPEnumerator)keyEnumerator
00340 {
00341 return [_keys objectEnumerator];
00342 }
00343
00347 - (CPEnumerator)objectEnumerator
00348 {
00349 return [[_CPDictionaryValueEnumerator alloc] initWithDictionary:self];
00350 }
00351
00355 - (BOOL)isEqualToDictionary:(CPDictionary)aDictionary
00356 {
00357 if (self === aDictionary)
00358 return YES;
00359
00360 var count = [self count];
00361
00362 if (count !== [aDictionary count])
00363 return NO;
00364
00365 var index = count;
00366
00367 while (index--)
00368 {
00369 var currentKey = _keys[index],
00370 lhsObject = _buckets[currentKey],
00371 rhsObject = aDictionary._buckets[currentKey];
00372
00373 if (lhsObject === rhsObject)
00374 continue;
00375
00376 if (lhsObject && lhsObject.isa && rhsObject && rhsObject.isa && [lhsObject respondsToSelector:@selector(isEqual:)] && [lhsObject isEqual:rhsObject])
00377 continue;
00378
00379 return NO;
00380 }
00381
00382 return YES;
00383 }
00384
00385 - (BOOL)isEqual:(id)anObject
00386 {
00387 if (self === anObject)
00388 return YES;
00389
00390 if (![anObject isKindOfClass:[CPDictionary class]])
00391 return NO;
00392
00393 return [self isEqualToDictionary:anObject];
00394 }
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00424 - (id)objectForKey:(CPString)aKey
00425 {
00426 var object = _buckets[aKey];
00427
00428 return (object === undefined) ? nil : object;
00429 }
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00455 - (void)removeAllObjects
00456 {
00457 self.removeAllValues();
00458 }
00459
00464 - (void)removeObjectForKey:(id)aKey
00465 {
00466 self.removeValueForKey(aKey);
00467 }
00468
00473 - (void)removeObjectsForKeys:(CPArray)keysForRemoval
00474 {
00475 var index = keysForRemoval.length;
00476
00477 while (index--)
00478 self.removeValueForKey(keysForRemoval[index]);
00479 }
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00498 - (void)setObject:(id)anObject forKey:(id)aKey
00499 {
00500 self.setValueForKey(aKey, anObject);
00501 }
00502
00506 - (void)addEntriesFromDictionary:(CPDictionary)aDictionary
00507 {
00508 if (!aDictionary)
00509 return;
00510
00511 var keys = [aDictionary allKeys],
00512 index = [keys count];
00513
00514 while (index--)
00515 {
00516 var key = keys[index];
00517
00518 [self setObject:[aDictionary objectForKey:key] forKey:key];
00519 }
00520 }
00521
00525 - (CPString)description
00526 {
00527 return self.toString();
00528 }
00529
00530 - (BOOL)containsKey:(id)aKey
00531 {
00532 var value = [self objectForKey:aKey];
00533 return ((value !== nil) && (value !== undefined));
00534 }
00535 @end
00536
00537 @implementation CPDictionary (CPCoding)
00538
00539
00540
00541
00542
00543
00544 - (id)initWithCoder:(CPCoder)aCoder
00545 {
00546 return [aCoder _decodeDictionaryOfObjectsForKey:@"CP.objects"];
00547 }
00548
00553 - (void)encodeWithCoder:(CPCoder)aCoder
00554 {
00555 [aCoder _encodeDictionaryOfObjects:self forKey:@"CP.objects"];
00556 }
00557
00558 @end
00559
00568 @implementation CPMutableDictionary : CPDictionary
00569
00570 @end
00571
00572 CFDictionary.prototype.isa = CPDictionary;
00573 CFMutableDictionary.prototype.isa = CPMutableDictionary;