This is NSDictionary.m in view mode; [Download] [Up]
/* NSDictionary.m Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea. All rights reserved. Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro> This file is part of libFoundation. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. We disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness, in no event shall we be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. */ #include <stdarg.h> #include <stdio.h> #include <Foundation/common.h> #include <Foundation/NSObject.h> #include <Foundation/NSDictionary.h> #include <Foundation/NSArray.h> #include <Foundation/NSData.h> #include <Foundation/NSRange.h> #include <Foundation/NSString.h> #include <Foundation/NSAutoreleasePool.h> #include <Foundation/NSException.h> #include <Foundation/NSCoder.h> #include <Foundation/exceptions/GeneralExceptions.h> #include "NSConcreteDictionary.h" @interface __KeyValueDescription : NSObject { @public NSString* keyDescription; NSString* valueDescription; } @end /* __KeyValueDescription */ @implementation __KeyValueDescription - (NSComparisonResult)compare:(__KeyValueDescription*)other { return [keyDescription compare:other->keyDescription]; } @end /* __KeyValueDescription */ /* * NSDictionary class */ @implementation NSDictionary /* Creating and Initializing an NSDictionary */ + (id)allocWithZone:(NSZone *)zone { return NSAllocateObject( (self == [NSDictionary class]) ? [NSConcreteDictionary class] : self, 0, zone); } + (id)dictionary { return [[[self alloc] initWithDictionary:nil] autorelease]; } + (id)dictionaryWithContentsOfFile:(NSString*)path { return [[[self alloc] initWithContentsOfFile:path] autorelease]; } + (id)dictionaryWithObjects:(NSArray*)objects forKeys:(NSArray*)keys { return [[[self alloc] initWithObjects:objects forKeys:keys] autorelease]; } + (id)dictionaryWithObjects:(id*)objects forKeys:(id*)keys count:(unsigned int)count; { return [[[self alloc] initWithObjects:objects forKeys:keys count:count] autorelease]; } + (id)dictionaryWithObjectsAndKeys:(id)firstObject, ... { id dict = [self alloc]; va_list va; va_start(va, firstObject); [dict initWithObjectsAndKeys:firstObject arguments:va]; va_end(va); return [dict autorelease]; } + (id)dictionaryWithDictionary:(NSDictionary*)aDict { return [[[self alloc] initWithDictionary:aDict] autorelease]; } + (id)dictionaryWithObject:object forKey:key { return [[[self alloc] initWithObjects:&object forKeys:&key count:1] autorelease]; } - (id)initWithContentsOfFile:(NSString*)fileName { id plist = nil; TRY { plist = [[NSString stringWithContentsOfFile:fileName] propertyList]; if (![plist isKindOfClass:[NSDictionary class]]) plist = nil; } END_TRY OTHERWISE { plist = nil; } END_CATCH if (plist == nil) { [self autorelease]; return nil; } else return [self initWithDictionary:plist]; } - (id)initWithDictionary:(NSDictionary*)dictionary copyItems:(BOOL)flag { NSEnumerator* keye = [dictionary keyEnumerator]; unsigned count = [dictionary count]; id *keys = Malloc(sizeof(id)*count); id *values = Malloc(sizeof(id)*count); id key; count = 0; while ((key = [keye nextObject])) { keys[count] = key; values[count] = [dictionary objectForKey:key]; if (flag) { keys[count] = [[keys[count] copyWithZone:NULL] autorelease]; values[count] = [[values[count] copyWithZone:NULL] autorelease]; } count++; } [self initWithObjects:values forKeys:keys count:count]; Free(keys); Free(values); return self; } - (id)initWithDictionary:(NSDictionary*)dictionary { return [self initWithDictionary:dictionary copyItems:NO]; } - (id)initWithObjectsAndKeys:(id)firstObject,... { va_list va; va_start(va, firstObject); [self initWithObjectsAndKeys:firstObject arguments:va]; va_end(va); return self; } - (id)initWithObjects:(NSArray*)objects forKeys:(NSArray*)keys { unsigned int i, count = [objects count]; id *mkeys; id *mobjs; if (count != [keys count]) THROW([[InvalidArgumentException alloc] initWithReason: @"NSDictionary initWithObjects:forKeys must \ have both arguments of the same size"]); mkeys = Malloc(sizeof(id)*count); mobjs = Malloc(sizeof(id)*count); for (i = 0; i < count; i++) { mkeys[i] = [keys objectAtIndex:i]; mobjs[i] = [objects objectAtIndex:i]; } [self initWithObjects:mobjs forKeys:mkeys count:count]; Free(mkeys); Free(mobjs); return self; } - (id)initWithObjects:(id*)objects forKeys:(id*)keys count:(unsigned int)count { [self subclassResponsibility:_cmd]; return self; } /* Accessing Keys and Values */ - (NSArray*)allKeys { id array; id *objs = Malloc(sizeof(id)*[self count]); id keys = [self keyEnumerator]; id key; unsigned int index = 0; while ((key = [keys nextObject])) objs[index++] = key; array = [[[NSArray alloc] initWithObjects:objs count:index] autorelease]; Free(objs); return array; } - (NSArray*)allKeysForObject:(id)object { id array; id *objs = Malloc(sizeof(id)*[self count]); id keys = [self keyEnumerator]; id key; unsigned int index = 0; while ((key = [keys nextObject])) if ([object isEqual:[self objectForKey:key]]) objs[index++] = key; array = [[[NSArray alloc] initWithObjects:objs count:index] autorelease]; Free(objs); return array; } - (NSArray*)allValues { id array; id *objs = Malloc(sizeof(id)*[self count]); id keys = [self objectEnumerator]; id obj; unsigned int index = 0; while ((obj = [keys nextObject])) objs[index++] = obj; array = [[[NSArray alloc] initWithObjects:objs count:index] autorelease]; Free(objs); return array; } - (NSEnumerator*)keyEnumerator { [self subclassResponsibility:_cmd]; return nil; } - (NSEnumerator*)objectEnumerator { return [[[_NSDictionaryObjectEnumerator alloc] initWithDictionary:self] autorelease]; } - (id)objectForKey:(id)aKey; { [self subclassResponsibility:_cmd]; return nil; } - (NSArray*)objectsForKeys:(NSArray*)keys notFoundMarker:notFoundObj { int count = [keys count]; id* objs = Malloc(sizeof(id)*count); id ret; for (count--; count >= 0; count--) { id ret = [self objectForKey:[keys objectAtIndex:count]]; objs[count] = ret ? ret : notFoundObj; } ret = [[[NSArray alloc] initWithObjects:objs count:count] autorelease]; Free(objs); return ret; } /* Counting Entries */ - (unsigned int)count; { [self subclassResponsibility:_cmd]; return 0; } /* * Comparing Dictionaries */ - (BOOL)isEqualToDictionary:(NSDictionary*)other { id keys, key; if( other == self ) return YES; if ([self count] != [other count] || other == nil) return NO; keys = [self keyEnumerator]; while ((key = [keys nextObject])) if ([[self objectForKey:key] isEqual:[other objectForKey:key]]==NO) return NO; return YES; } /* Storing Dictionaries */ - (NSString*)descriptionWithLocale:(NSDictionary*)locale indent:(unsigned int)indent; { id key, value; NSEnumerator* enumerator; unsigned indent1 = indent + 4; NSMutableArray* keyDescriptions; id pool = [NSAutoreleasePool new]; SEL sel; IMP imp; __KeyValueDescription* descHolder; NSMutableString* description = [[NSMutableString stringWithCString:"{\n"] retain]; NSMutableString* indentation = [NSString stringWithFormat: [NSString stringWithFormat:@"%%%dc", indent1], ' ']; if(![self count]) { [pool release]; return @"{}"; } enumerator = [self keyEnumerator]; keyDescriptions = [NSMutableArray arrayWithCapacity:[self count]]; while((key = [enumerator nextObject])) { descHolder = [__KeyValueDescription alloc]; value = [self objectForKey:key]; if ([key respondsToSelector:@selector(descriptionWithLocale:indent:)]) descHolder->keyDescription = [key descriptionWithLocale:locale indent:indent1]; else if ([key respondsToSelector:@selector(descriptionWithLocale:)]) descHolder->keyDescription = [key descriptionWithLocale:locale]; else descHolder->keyDescription = [key stringRepresentation]; if ([value respondsToSelector:@selector(descriptionWithLocale:indent:)]) descHolder->valueDescription = [value descriptionWithLocale:locale indent:indent1]; else if ([value respondsToSelector:@selector(descriptionWithLocale:)]) descHolder->valueDescription = [value descriptionWithLocale:locale]; else descHolder->valueDescription = [value stringRepresentation]; Assert([descHolder->keyDescription isKindOfClass:[NSString class]]); Assert([descHolder->valueDescription isKindOfClass:[NSString class]]); [keyDescriptions addObject:descHolder]; [descHolder release]; } [keyDescriptions sortUsingSelector:@selector(compare:)]; sel = @selector(appendString:); imp = [description methodForSelector:sel]; Assert(imp); enumerator = [keyDescriptions objectEnumerator]; while((descHolder = [enumerator nextObject])) { (*imp)(description, sel, indentation); (*imp)(description, sel, descHolder->keyDescription); (*imp)(description, sel, @" = "); (*imp)(description, sel, descHolder->valueDescription); (*imp)(description, sel, @";\n"); } (*imp)(description, sel, indent ? [NSMutableString stringWithFormat: [NSString stringWithFormat:@"%%%dc}", indent], ' '] : [NSMutableString stringWithCString:"}"]); [pool release]; return [description autorelease]; } - (NSString*)descriptionInStringsFileFormat { id key, value; NSMutableArray* keys; NSEnumerator* enumerator; NSMutableString* description = [[NSMutableString new] autorelease]; id pool = [NSAutoreleasePool new]; keys = [[[self allKeys] mutableCopy] autorelease]; [keys sortUsingSelector:@selector(compare:)]; enumerator = [keys objectEnumerator]; while((key = [enumerator nextObject])) { value = [self objectForKey:key]; Assert([key isKindOfClass:[NSString class]]); Assert([value isKindOfClass:[NSString class]]); [description appendString:[key stringRepresentation]]; [description appendString:@" = "]; [description appendString:[value stringRepresentation]]; [description appendString:@";\n"]; } [pool release]; return description; } - (NSString*)descriptionWithLocale:(NSDictionary*)locale { return [self descriptionWithLocale:locale indent:0]; } - (NSString*)description { return [self descriptionWithLocale:nil indent:0]; } - (NSString*)stringRepresentation { return [self descriptionWithLocale:nil indent:0]; } - (BOOL)writeToFile:(NSString*)path atomically:(BOOL)useAuxiliaryFile { id description = [self description]; NSData* data = [NSData dataWithBytes:[description cString] length:[description cStringLength]]; return writeToFile(path, data, useAuxiliaryFile); } /* From adopted/inherited protocols */ - (unsigned int)hash { return [self count]; } - (BOOL)isEqual:(id)anObject { if ([anObject isKindOfClass:[NSDictionary class]] == NO) return NO; return [self isEqualToDictionary:anObject]; } - (id)copyWithZone:(NSZone*)zone { if (NSShouldRetainWithZone(self, zone)) return [self retain]; else return [[[self class] allocWithZone:zone] initWithDictionary:self copyItems:YES]; } - (id)mutableCopyWithZone:(NSZone*)zone { return [[NSMutableDictionary allocWithZone:zone] initWithDictionary:self]; } - (Class)classForCoder { return [NSDictionary class]; } - (void)encodeWithCoder:(NSCoder*)aCoder { int count = [self count]; NSEnumerator* enumerator = [self keyEnumerator]; id key, value; [aCoder encodeValueOfObjCType:@encode(int) at:&count]; while((key = [enumerator nextObject])) { value = [self objectForKey:key]; [aCoder encodeObject:key]; [aCoder encodeObject:value]; } } - (id)initWithCoder:(NSCoder*)aDecoder { int i, count; id *keys, *values; [aDecoder decodeValueOfObjCType:@encode(int) at:&count]; keys = Malloc(sizeof(id) * count); values = Malloc(sizeof(id) * count); for(i = 0; i < count; i++) { keys[i] = [aDecoder decodeObject]; values[i] = [aDecoder decodeObject]; } [self initWithObjects:keys forKeys:keys count:count]; Free(keys); Free(values); return self; } @end /* NSDictionary */ /* * Extensions to NSDictionary */ @implementation NSDictionary(NSDictionaryExtensions) - (id)initWithObjectsAndKeys:(id)firstObject arguments:(va_list)argList { id object; id *ka, *oa; va_list va = argList; int count = 0; for (object = firstObject; object; object = va_arg(va,id)) { if (!va_arg(va,id)) THROW([[InvalidArgumentException alloc] initWithReason:@"Nil key to be added in dictionary"]); count++; } ka = Malloc(sizeof(id)*count); oa = Malloc(sizeof(id)*count); for (count=0, object=firstObject; object; object=va_arg(argList,id)) { ka[count] = va_arg(argList,id); oa[count] = object; count++; } [self initWithObjects:oa forKeys:ka count:count]; Free(ka); Free(oa); return self; } @end; /* * NSMutableDictionary class */ @implementation NSMutableDictionary /* Creating and Initializing an NSDictionary */ + (id)allocWithZone:(NSZone *)zone { return NSAllocateObject( (self == [NSMutableDictionary class]) ? [NSConcreteMutableDictionary class] : self, 0, zone); } + (id)dictionaryWithCapacity:(unsigned int)aNumItems { return [[[self alloc] initWithCapacity:aNumItems] autorelease]; } - (id)initWithCapacity:(unsigned int)aNumItems { [self subclassResponsibility:_cmd]; return self; } - (id)copyWithZone:(NSZone*)zone { return [[NSDictionary allocWithZone:zone] initWithDictionary:self copyItems:YES]; } /* Adding and Removing Entries */ - (void)addEntriesFromDictionary:(NSDictionary*)otherDictionary { id nodes = [otherDictionary keyEnumerator]; id key; while ((key = [nodes nextObject])) [self setObject:[otherDictionary objectForKey:key] forKey:key]; } - (void)removeAllObjects { id keys = [self keyEnumerator]; id key; while ((key=[keys nextObject])) [self removeObjectForKey:key]; } - (void)removeObjectForKey:(id)theKey { [self subclassResponsibility:_cmd]; } - (void)removeObjectsForKeys:(NSArray*)keyArray { unsigned int index, count = [keyArray count]; for (index = 0; index<count; index++) [self removeObjectForKey:[keyArray objectAtIndex:index]]; } - (void)setObject:(id)anObject forKey:(id)aKey { [self subclassResponsibility:_cmd]; } - (void)setDictionary:(NSDictionary*)otherDictionary { [self removeAllObjects]; [self addEntriesFromDictionary:otherDictionary]; } - (Class)classForCoder { return [NSMutableDictionary class]; } @end /* NSMutableDictionary */ /* * NSDictionary Enumerator classes */ @implementation _NSDictionaryObjectEnumerator { NSDictionary* dict; NSEnumerator* keys; } - initWithDictionary:(NSDictionary*)_dict { dict = [_dict retain]; keys = [[_dict keyEnumerator] retain]; return self; } - (void)dealloc { [dict release]; [keys release]; [super dealloc]; } - nextObject { return [dict objectForKey:[keys nextObject]]; } @end /* _NSDictionaryObjectEnumerator */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.