26
#include <Foundation/NSDictionary.h>
27
#include <Foundation/NSAutoreleasePool.h>
28
#include <Foundation/NSUtilities.h>
29
#include <Foundation/NSString.h>
30
#include <Foundation/NSException.h>
31
#include <Foundation/NSPortCoder.h>
32
#include <Foundation/NSDebug.h>
26
#include "Foundation/NSDictionary.h"
27
#include "Foundation/NSAutoreleasePool.h"
28
#include "Foundation/NSUtilities.h"
29
#include "Foundation/NSString.h"
30
#include "Foundation/NSException.h"
31
#include "Foundation/NSPortCoder.h"
32
#include "Foundation/NSDebug.h"
33
// For private method _decodeArrayOfObjectsForKey:
34
#include "Foundation/NSKeyedArchiver.h"
34
#include <base/behavior.h>
36
#include "GNUstepBase/GSObjCRuntime.h"
37
39
* The 'Fastmap' stuff provides an inline implementation of a mapping
41
43
#define GSI_MAP_VTYPES GSUNION_OBJ
42
44
#define GSI_MAP_HASH(M, X) [X.obj hash]
43
45
#define GSI_MAP_EQUAL(M, X,Y) [X.obj isEqual: Y.obj]
44
#define GSI_MAP_RETAIN_KEY(M, X) ((id)(X).obj) = \
46
#define GSI_MAP_RETAIN_KEY(M, X) ((X).obj) = \
45
47
[((id)(X).obj) copyWithZone: map->zone]
47
#include <base/GSIMap.h>
49
#include "GNUstepBase/GSIMap.h"
49
51
@interface GSDictionary : NSDictionary
98
105
- (void) encodeWithCoder: (NSCoder*)aCoder
100
unsigned count = map.nodeCount;
101
SEL sel = @selector(encodeObject:);
102
IMP imp = [aCoder methodForSelector: sel];
103
GSIMapEnumerator_t enumerator = GSIMapEnumeratorForMap(&map);
104
GSIMapNode node = GSIMapEnumeratorNextNode(&enumerator);
107
if ([aCoder allowsKeyedCoding])
109
[super encodeWithCoder: aCoder];
113
unsigned count = map.nodeCount;
114
SEL sel = @selector(encodeObject:);
115
IMP imp = [aCoder methodForSelector: sel];
116
GSIMapEnumerator_t enumerator = GSIMapEnumeratorForMap(&map);
117
GSIMapNode node = GSIMapEnumeratorNextNode(&enumerator);
106
[aCoder encodeValueOfObjCType: @encode(unsigned) at: &count];
109
(*imp)(aCoder, sel, node->key.obj);
110
(*imp)(aCoder, sel, node->value.obj);
111
node = GSIMapEnumeratorNextNode(&enumerator);
119
[aCoder encodeValueOfObjCType: @encode(unsigned) at: &count];
122
(*imp)(aCoder, sel, node->key.obj);
123
(*imp)(aCoder, sel, node->value.obj);
124
node = GSIMapEnumeratorNextNode(&enumerator);
126
GSIMapEndEnumerator(&enumerator);
117
132
return map.nodeCount;
137
return [self initWithObjects: 0 forKeys: 0 count: 0];
120
140
- (id) initWithCoder: (NSCoder*)aCoder
125
SEL sel = @selector(decodeValueOfObjCType:at:);
126
IMP imp = [aCoder methodForSelector: sel];
127
const char *type = @encode(id);
129
[aCoder decodeValueOfObjCType: @encode(unsigned)
132
GSIMapInitWithZoneAndCapacity(&map, GSObjCZone(self), count);
135
(*imp)(aCoder, sel, type, &key);
136
(*imp)(aCoder, sel, type, &value);
137
GSIMapAddPairNoRetain(&map, (GSIMapKey)key, (GSIMapVal)value);
142
if ([aCoder allowsKeyedCoding])
144
self = [super initWithCoder: aCoder];
151
SEL sel = @selector(decodeValueOfObjCType:at:);
152
IMP imp = [aCoder methodForSelector: sel];
153
const char *type = @encode(id);
155
[aCoder decodeValueOfObjCType: @encode(unsigned)
158
GSIMapInitWithZoneAndCapacity(&map, GSObjCZone(self), count);
161
(*imp)(aCoder, sel, type, &key);
162
(*imp)(aCoder, sel, type, &value);
163
GSIMapAddPairNoRetain(&map, (GSIMapKey)key, (GSIMapVal)value);
193
220
NSEnumerator *e = [other keyEnumerator];
194
221
IMP nxtObj = [e methodForSelector: nxtSel];
195
222
IMP otherObj = [other methodForSelector: objSel];
223
BOOL isProxy = [other isProxy];
198
226
for (i = 0; i < c; i++)
201
id k = (*nxtObj)(e, nxtSel);
202
id o = (*otherObj)(other, objSel, k);
235
o = [other objectForKey: k];
239
k = (*nxtObj)(e, nxtSel);
240
o = (*otherObj)(other, objSel, k);
204
242
k = [k copyWithZone: z];
279
- (BOOL) isEqualToDictionary: (NSDictionary*)other
287
count = map.nodeCount;
288
if (count == [other count])
292
GSIMapEnumerator_t enumerator;
294
IMP otherObj = [other methodForSelector: objSel];
296
enumerator = GSIMapEnumeratorForMap(&map);
297
while ((node = GSIMapEnumeratorNextNode(&enumerator)) != 0)
299
id o1 = node->value.obj;
300
id o2 = (*otherObj)(other, objSel, node->key.obj);
302
if (o1 != o2 && [o1 isEqual: o2] == NO)
304
GSIMapEndEnumerator(&enumerator);
308
GSIMapEndEnumerator(&enumerator);
241
315
- (NSEnumerator*) keyEnumerator
243
317
return AUTORELEASE([[GSDictionaryKeyEnumerator allocWithZone:
273
347
if (self == [GSMutableDictionary class])
275
behavior_class_add_class(self, [GSDictionary class]);
349
GSObjCAddClassBehavior(self, [GSDictionary class]);
353
- (id) copyWithZone: (NSZone*)zone
355
NSDictionary *copy = [GSDictionary allocWithZone: zone];
357
return [copy initWithDictionary: self copyItems: NO];
362
return [self initWithCapacity: 0];
279
365
/* Designated initialiser */
280
366
- (id) initWithCapacity: (unsigned)cap
372
- (id) makeImmutableCopyOnFail: (BOOL)force
375
GSDebugAllocationRemove(isa, self);
377
isa = [GSDictionary class];
379
GSDebugAllocationAdd(isa, self);
286
384
- (void) setObject: (id)anObject forKey: (id)aKey
292
[NSException raise: NSInvalidArgumentException
293
format: @"Tried to add nil key to dictionary"];
392
e = [NSException exceptionWithName: NSInvalidArgumentException
393
reason: @"Tried to add nil key to dictionary"
295
397
if (anObject == nil)
297
[NSException raise: NSInvalidArgumentException
298
format: @"Tried to add nil value to dictionary"];
402
s = [NSString stringWithFormat:
403
@"Tried to add nil value for key '%@' to dictionary", aKey];
404
e = [NSException exceptionWithName: NSInvalidArgumentException
300
409
node = GSIMapNodeForKey(&map, (GSIMapKey)aKey);