1995-04-03 22:59:20 +00:00
|
|
|
/* NSDictionary - Dictionary object to store key/value pairs
|
1996-02-01 17:04:17 +00:00
|
|
|
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
1995-04-04 16:15:31 +00:00
|
|
|
|
1996-04-17 20:17:45 +00:00
|
|
|
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
1995-05-05 18:31:51 +00:00
|
|
|
From skeleton by: Adam Fedor <fedor@boulder.colorado.edu>
|
1995-04-03 22:59:20 +00:00
|
|
|
Date: Mar 1995
|
1995-04-04 16:15:31 +00:00
|
|
|
|
1996-05-12 00:56:10 +00:00
|
|
|
This file is part of the GNUstep Base Library.
|
1995-04-04 16:15:31 +00:00
|
|
|
|
1995-04-03 22:59:20 +00:00
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
1995-04-04 16:15:31 +00:00
|
|
|
|
1995-04-03 22:59:20 +00:00
|
|
|
You should have received a copy of the GNU Library General Public
|
|
|
|
License along with this library; if not, write to the Free
|
|
|
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
1995-04-04 16:15:31 +00:00
|
|
|
*/
|
1995-04-03 22:59:20 +00:00
|
|
|
|
1995-04-17 21:13:20 +00:00
|
|
|
#include <Foundation/NSDictionary.h>
|
1995-05-05 18:31:51 +00:00
|
|
|
#include <Foundation/NSGDictionary.h>
|
|
|
|
#include <Foundation/NSArray.h>
|
|
|
|
#include <Foundation/NSUtilities.h>
|
1996-04-17 15:23:00 +00:00
|
|
|
#include <gnustep/base/NSString.h>
|
1995-05-05 18:31:51 +00:00
|
|
|
#include <assert.h>
|
1995-04-03 22:59:20 +00:00
|
|
|
|
|
|
|
@implementation NSDictionary
|
|
|
|
|
1995-06-30 14:21:45 +00:00
|
|
|
static Class NSDictionary_concrete_class;
|
|
|
|
static Class NSMutableDictionary_concrete_class;
|
|
|
|
|
|
|
|
+ (void) _setConcreteClass: (Class)c
|
|
|
|
{
|
|
|
|
NSDictionary_concrete_class = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (void) _setMutableConcreteClass: (Class)c
|
|
|
|
{
|
|
|
|
NSMutableDictionary_concrete_class = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (Class) _concreteClass
|
|
|
|
{
|
|
|
|
return NSDictionary_concrete_class;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (Class) _mutableConcreteClass
|
|
|
|
{
|
|
|
|
return NSMutableDictionary_concrete_class;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (void) initialize
|
|
|
|
{
|
|
|
|
NSDictionary_concrete_class = [NSGDictionary class];
|
|
|
|
NSMutableDictionary_concrete_class = [NSGMutableDictionary class];
|
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
+ allocWithZone: (NSZone*)z
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1995-06-30 14:21:45 +00:00
|
|
|
return NSAllocateObject([self _concreteClass], 0, z);
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
+ dictionary
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1995-11-03 22:18:47 +00:00
|
|
|
return [[[self alloc] init]
|
1995-05-05 18:31:51 +00:00
|
|
|
autorelease];
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
+ dictionaryWithObjects: (id*)objects
|
|
|
|
forKeys: (NSString**)keys
|
|
|
|
count: (unsigned)count
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1995-11-03 22:18:47 +00:00
|
|
|
return [[[self alloc] initWithObjects:objects
|
|
|
|
forKeys:keys
|
|
|
|
count:count]
|
1995-05-05 18:31:51 +00:00
|
|
|
autorelease];
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
- initWithObjects: (NSArray*)objects forKeys: (NSArray*)keys
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1995-05-05 18:31:51 +00:00
|
|
|
int c = [objects count];
|
|
|
|
id os[c], ks[c];
|
|
|
|
int i;
|
|
|
|
|
|
|
|
assert(c == [keys count]); /* Should be NSException instead */
|
|
|
|
for (i = 0; i < c; i++)
|
|
|
|
{
|
|
|
|
os[i] = [objects objectAtIndex:i];
|
|
|
|
ks[i] = [keys objectAtIndex:i];
|
|
|
|
}
|
|
|
|
return [self initWithObjects:os forKeys:ks count:c];
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
+ dictionaryWithObjects: (NSArray*)objects forKeys: (NSArray*)keys
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1995-11-03 22:18:47 +00:00
|
|
|
return [[[self alloc] initWithObjects:objects forKeys:keys]
|
1995-05-05 18:31:51 +00:00
|
|
|
autorelease];
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
/* This is the designated initializer */
|
|
|
|
- initWithObjects: (id*)objects
|
|
|
|
forKeys: (NSString**)keys
|
|
|
|
count: (unsigned)count
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1996-02-01 17:04:17 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-04 16:15:31 +00:00
|
|
|
return 0;
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
/* Override superclass's designated initializer */
|
|
|
|
- init
|
|
|
|
{
|
|
|
|
return [self initWithObjects:NULL forKeys:NULL count:0];
|
|
|
|
}
|
|
|
|
|
|
|
|
- initWithDictionary: (NSDictionary*)other
|
|
|
|
{
|
|
|
|
int c = [other count];
|
|
|
|
id os[c], ks[c], k, e = [other keyEnumerator];
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
while ((k = [e nextObject]))
|
|
|
|
{
|
|
|
|
ks[i] = k;
|
|
|
|
os[i] = [other objectForKey:k];
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
return [self initWithObjects:os forKeys:ks count:c];
|
|
|
|
}
|
|
|
|
|
|
|
|
- initWithContentsOfFile: (NSString*)path
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1995-04-04 16:15:31 +00:00
|
|
|
[self notImplemented:_cmd];
|
|
|
|
return 0;
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
- (unsigned) count
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1996-02-01 17:04:17 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-04 16:15:31 +00:00
|
|
|
return 0;
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
- objectForKey: (NSString*)aKey
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1996-02-01 17:04:17 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-04 16:15:31 +00:00
|
|
|
return 0;
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
- (NSEnumerator*) keyEnumerator
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1996-02-01 17:04:17 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
1995-05-05 18:31:51 +00:00
|
|
|
return nil;
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
- (BOOL) isEqual: other
|
|
|
|
{
|
|
|
|
if ([other isKindOfClass:[NSDictionary class]])
|
|
|
|
return [self isEqualToDictionary:other];
|
|
|
|
return NO;
|
|
|
|
}
|
1995-04-03 22:59:20 +00:00
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
- (BOOL) isEqualToDictionary: (NSDictionary*)other
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1995-05-05 18:31:51 +00:00
|
|
|
if ([self count] != [other count])
|
|
|
|
return NO;
|
|
|
|
{
|
|
|
|
id k, e = [self keyEnumerator];
|
|
|
|
while ((k = [e nextObject]))
|
|
|
|
if (![[self objectForKey:k] isEqual:[other objectForKey:k]])
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
/* xxx Recheck this. */
|
|
|
|
return YES;
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
- (NSString*) description
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1996-05-13 16:39:21 +00:00
|
|
|
id desc;
|
|
|
|
id keyenum = [self keyEnumerator];
|
|
|
|
id key;
|
1996-05-13 17:28:00 +00:00
|
|
|
|
|
|
|
desc = [NSMutableString stringWithCapacity: 2];
|
|
|
|
[desc appendString: @"{"];
|
1996-05-13 17:29:49 +00:00
|
|
|
while ((key = [keyenum nextObject]))
|
1996-05-13 17:28:00 +00:00
|
|
|
{
|
|
|
|
/* I wish appendString: returned self*/
|
|
|
|
[desc appendString: [key description]];
|
|
|
|
[desc appendString: @" = "];
|
|
|
|
[desc appendString: [[self objectForKey: key] description]];
|
|
|
|
[desc appendString: @"; "];
|
|
|
|
}
|
|
|
|
[desc appendString: @"}"];
|
1996-05-13 16:39:21 +00:00
|
|
|
return desc;
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
- (NSString*) descriptionWithIndent: (unsigned)level
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1995-05-05 18:31:51 +00:00
|
|
|
return [NSString stringWithFormat:@"%*s%s",
|
1996-05-27 15:03:26 +00:00
|
|
|
level, "", [[self description] cStringNoCopy]];
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
- (NSArray*) allKeys
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1995-05-05 18:31:51 +00:00
|
|
|
id e = [self keyEnumerator];
|
|
|
|
int i, c = [self count];
|
|
|
|
id k[c];
|
|
|
|
|
|
|
|
for (i = 0; i < c; i++)
|
|
|
|
{
|
|
|
|
k[i] = [e nextObject];
|
|
|
|
assert(k[i]);
|
|
|
|
}
|
|
|
|
assert(![e nextObject]);
|
|
|
|
return [[[NSArray alloc] initWithObjects:k count:c]
|
|
|
|
autorelease];
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
- (NSArray*) allValues
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1995-05-05 18:31:51 +00:00
|
|
|
id e = [self objectEnumerator];
|
|
|
|
int i, c = [self count];
|
|
|
|
id k[c];
|
|
|
|
|
|
|
|
for (i = 0; i < c; i++)
|
|
|
|
{
|
|
|
|
k[i] = [e nextObject];
|
|
|
|
assert(k[i]);
|
|
|
|
}
|
|
|
|
assert(![e nextObject]);
|
|
|
|
return [[[NSArray alloc] initWithObjects:k count:c]
|
|
|
|
autorelease];
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
- (NSArray*) allKeysForObject: anObject
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1995-05-05 18:31:51 +00:00
|
|
|
id k, e = [self keyEnumerator];
|
|
|
|
id a[[self count]];
|
|
|
|
int c = 0;
|
|
|
|
|
|
|
|
while ((k = [e nextObject]))
|
1996-04-08 17:19:16 +00:00
|
|
|
if ([anObject isEqual: [self objectForKey: k]])
|
1995-05-05 18:31:51 +00:00
|
|
|
a[c++] = k;
|
1996-04-08 17:19:16 +00:00
|
|
|
return [[[NSArray alloc] initWithObjects: a count: c]
|
1995-05-05 18:31:51 +00:00
|
|
|
autorelease];
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile
|
|
|
|
{
|
1995-04-04 16:15:31 +00:00
|
|
|
[self notImplemented:_cmd];
|
|
|
|
return 0;
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
- (NSEnumerator*) objectEnumerator
|
|
|
|
{
|
1996-02-01 17:04:17 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
1995-05-05 18:31:51 +00:00
|
|
|
return nil;
|
|
|
|
}
|
1995-04-03 22:59:20 +00:00
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
- copyWithZone: (NSZone*)z
|
|
|
|
{
|
1995-06-30 14:21:45 +00:00
|
|
|
/* a deep copy */
|
|
|
|
int count = [self count];
|
|
|
|
id objects[count];
|
|
|
|
NSString *keys[count];
|
|
|
|
id enumerator = [self keyEnumerator];
|
|
|
|
id key;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; (key = [enumerator nextObject]); i++)
|
|
|
|
{
|
|
|
|
keys[i] = [key copyWithZone:z];
|
|
|
|
objects[i] = [[self objectForKey:key] copyWithZone:z];
|
|
|
|
}
|
|
|
|
return [[[[self class] _concreteClass] alloc]
|
|
|
|
initWithObjects:objects
|
|
|
|
forKeys:keys
|
|
|
|
count:count];
|
1995-05-05 18:31:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- mutableCopyWithZone: (NSZone*)z
|
|
|
|
{
|
1995-06-30 14:21:45 +00:00
|
|
|
/* a shallow copy */
|
|
|
|
return [[[[[self class] _mutableConcreteClass] _mutableConcreteClass] alloc]
|
|
|
|
initWithDictionary:self];
|
1995-05-05 18:31:51 +00:00
|
|
|
}
|
1995-04-03 22:59:20 +00:00
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation NSMutableDictionary
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
+ allocWithZone: (NSZone*)z
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1995-06-30 14:21:45 +00:00
|
|
|
return NSAllocateObject([self _mutableConcreteClass], 0, z);
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
+ dictionaryWithCapacity: (unsigned)numItems
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1995-11-03 22:18:47 +00:00
|
|
|
return [[[self alloc] initWithCapacity:numItems]
|
1995-05-05 18:31:51 +00:00
|
|
|
autorelease];
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
/* This is the designated initializer */
|
|
|
|
- initWithCapacity: (unsigned)numItems
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1996-02-01 17:04:17 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-04 16:15:31 +00:00
|
|
|
return 0;
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
/* Override superclass's designated initializer */
|
|
|
|
- initWithObjects: (id*)objects
|
|
|
|
forKeys: (NSString**)keys
|
|
|
|
count: (unsigned)count
|
|
|
|
{
|
|
|
|
[self initWithCapacity:count];
|
|
|
|
while (count--)
|
|
|
|
[self setObject:objects[count] forKey:keys[count]];
|
|
|
|
return self;
|
|
|
|
}
|
1995-04-03 22:59:20 +00:00
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
- (void) setObject:anObject forKey:(NSString *)aKey
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1996-02-01 17:04:17 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
- (void) removeObjectForKey:(NSString *)aKey
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1996-02-01 17:04:17 +00:00
|
|
|
[self subclassResponsibility:_cmd];
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
- (void) removeAllObjects
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1995-05-05 18:31:51 +00:00
|
|
|
id k, e = [self keyEnumerator];
|
|
|
|
while ((k = [e nextObject]))
|
|
|
|
[self removeObjectForKey:k];
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
- (void) removeObjectsForKeys: (NSArray*)keyArray
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1995-05-05 18:31:51 +00:00
|
|
|
int c = [keyArray count];
|
|
|
|
while (c--)
|
|
|
|
[self removeObjectForKey:[keyArray objectAtIndex:c]];
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
1995-05-05 18:31:51 +00:00
|
|
|
- (void) addEntriesFromDictionary: (NSDictionary*)other
|
1995-04-03 22:59:20 +00:00
|
|
|
{
|
1995-05-05 18:31:51 +00:00
|
|
|
id k, e = [other keyEnumerator];
|
|
|
|
while ((k = [e nextObject]))
|
|
|
|
[self setObject:[other objectForKey:k] forKey:k];
|
1995-04-03 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@end
|