~ubuntu-branches/ubuntu/karmic/gnustep-base/karmic

« back to all changes in this revision

Viewing changes to Source/GSDictionary.m

  • Committer: Bazaar Package Importer
  • Author(s): Eric Heintzmann
  • Date: 2005-04-17 00:14:38 UTC
  • mfrom: (1.2.1 upstream) (2.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050417001438-enf0y07c9tku85z1
Tags: 1.10.3-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
   */
23
23
 
24
24
 
25
 
#include <config.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>
 
25
#include "config.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"
33
35
 
34
 
#include <base/behavior.h>
 
36
#include "GNUstepBase/GSObjCRuntime.h"
35
37
 
36
38
/*
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]
46
48
 
47
 
#include        <base/GSIMap.h>
 
49
#include        "GNUstepBase/GSIMap.h"
48
50
 
49
51
@interface GSDictionary : NSDictionary
50
52
{
84
86
    }
85
87
}
86
88
 
 
89
- (id) copyWithZone: (NSZone*)zone
 
90
{
 
91
  return RETAIN(self);
 
92
}
 
93
 
87
94
- (unsigned) count
88
95
{
89
96
  return map.nodeCount;
97
104
 
98
105
- (void) encodeWithCoder: (NSCoder*)aCoder
99
106
{
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])
 
108
    {
 
109
      [super encodeWithCoder: aCoder];
 
110
    }
 
111
  else
 
112
    {
 
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);
105
118
 
106
 
  [aCoder encodeValueOfObjCType: @encode(unsigned) at: &count];
107
 
  while (node != 0)
108
 
    {
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];
 
120
      while (node != 0)
 
121
        {
 
122
          (*imp)(aCoder, sel, node->key.obj);
 
123
          (*imp)(aCoder, sel, node->value.obj);
 
124
          node = GSIMapEnumeratorNextNode(&enumerator);
 
125
        }
 
126
      GSIMapEndEnumerator(&enumerator);
112
127
    }
113
128
}
114
129
 
117
132
  return map.nodeCount;
118
133
}
119
134
 
 
135
- (id) init
 
136
{
 
137
  return [self initWithObjects: 0 forKeys: 0 count: 0];
 
138
}
 
139
 
120
140
- (id) initWithCoder: (NSCoder*)aCoder
121
141
{
122
 
  unsigned      count;
123
 
  id            key;
124
 
  id            value;
125
 
  SEL           sel = @selector(decodeValueOfObjCType:at:);
126
 
  IMP           imp = [aCoder methodForSelector: sel];
127
 
  const char    *type = @encode(id);
128
 
 
129
 
  [aCoder decodeValueOfObjCType: @encode(unsigned)
130
 
                             at: &count];
131
 
 
132
 
  GSIMapInitWithZoneAndCapacity(&map, GSObjCZone(self), count);
133
 
  while (count-- > 0)
134
 
    {
135
 
      (*imp)(aCoder, sel, type, &key);
136
 
      (*imp)(aCoder, sel, type, &value);
137
 
      GSIMapAddPairNoRetain(&map, (GSIMapKey)key, (GSIMapVal)value);
 
142
  if ([aCoder allowsKeyedCoding])
 
143
    {
 
144
      self = [super initWithCoder: aCoder];
 
145
    }
 
146
  else
 
147
    {
 
148
      unsigned  count;
 
149
      id                key;
 
150
      id                value;
 
151
      SEL               sel = @selector(decodeValueOfObjCType:at:);
 
152
      IMP               imp = [aCoder methodForSelector: sel];
 
153
      const char        *type = @encode(id);
 
154
 
 
155
      [aCoder decodeValueOfObjCType: @encode(unsigned)
 
156
                                 at: &count];
 
157
 
 
158
      GSIMapInitWithZoneAndCapacity(&map, GSObjCZone(self), count);
 
159
      while (count-- > 0)
 
160
        {
 
161
          (*imp)(aCoder, sel, type, &key);
 
162
          (*imp)(aCoder, sel, type, &value);
 
163
          GSIMapAddPairNoRetain(&map, (GSIMapKey)key, (GSIMapVal)value);
 
164
        }
138
165
    }
139
166
  return self;
140
167
}
142
169
/* Designated initialiser */
143
170
- (id) initWithObjects: (id*)objs forKeys: (id*)keys count: (unsigned)c
144
171
{
145
 
  int   i;
 
172
  unsigned int  i;
146
173
 
147
174
  GSIMapInitWithZoneAndCapacity(&map, GSObjCZone(self), c);
148
175
  for (i = 0; i < c; i++)
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];
196
224
      unsigned          i;
197
225
 
198
226
      for (i = 0; i < c; i++)
199
227
        {
200
228
          GSIMapNode    node;
201
 
          id            k = (*nxtObj)(e, nxtSel);
202
 
          id            o = (*otherObj)(other, objSel, k);
 
229
          id            k;
 
230
          id            o;
203
231
 
 
232
          if (isProxy == YES)
 
233
            {
 
234
              k = [e nextObject];
 
235
              o = [other objectForKey: k];
 
236
            }
 
237
          else
 
238
            {
 
239
              k = (*nxtObj)(e, nxtSel);
 
240
              o = (*otherObj)(other, objSel, k);
 
241
            }
204
242
          k = [k copyWithZone: z];
205
243
          if (k == nil)
206
244
            {
238
276
  return self;
239
277
}
240
278
 
 
279
- (BOOL) isEqualToDictionary: (NSDictionary*)other
 
280
{
 
281
  unsigned      count;
 
282
 
 
283
  if (other == self)
 
284
    {
 
285
      return YES;
 
286
    }
 
287
  count = map.nodeCount;
 
288
  if (count == [other count])
 
289
    {
 
290
      if (count > 0)
 
291
        {
 
292
          GSIMapEnumerator_t    enumerator;
 
293
          GSIMapNode            node;
 
294
          IMP                   otherObj = [other methodForSelector: objSel];
 
295
 
 
296
          enumerator = GSIMapEnumeratorForMap(&map);
 
297
          while ((node = GSIMapEnumeratorNextNode(&enumerator)) != 0)
 
298
            {
 
299
              id o1 = node->value.obj;
 
300
              id o2 = (*otherObj)(other, objSel, node->key.obj);
 
301
 
 
302
              if (o1 != o2 && [o1 isEqual: o2] == NO)
 
303
                {
 
304
                  GSIMapEndEnumerator(&enumerator);
 
305
                  return NO;
 
306
                }
 
307
            }
 
308
          GSIMapEndEnumerator(&enumerator);
 
309
        }
 
310
      return YES;
 
311
    }
 
312
  return NO;
 
313
}
 
314
 
241
315
- (NSEnumerator*) keyEnumerator
242
316
{
243
317
  return AUTORELEASE([[GSDictionaryKeyEnumerator allocWithZone:
272
346
{
273
347
  if (self == [GSMutableDictionary class])
274
348
    {
275
 
      behavior_class_add_class(self, [GSDictionary class]);
 
349
      GSObjCAddClassBehavior(self, [GSDictionary class]);
276
350
    }
277
351
}
278
352
 
 
353
- (id) copyWithZone: (NSZone*)zone
 
354
{
 
355
  NSDictionary  *copy = [GSDictionary allocWithZone: zone];
 
356
 
 
357
  return [copy initWithDictionary: self copyItems: NO];
 
358
}
 
359
 
 
360
- (id) init
 
361
{
 
362
  return [self initWithCapacity: 0];
 
363
}
 
364
 
279
365
/* Designated initialiser */
280
366
- (id) initWithCapacity: (unsigned)cap
281
367
{
283
369
  return self;
284
370
}
285
371
 
 
372
- (id) makeImmutableCopyOnFail: (BOOL)force
 
373
{
 
374
#ifndef NDEBUG
 
375
  GSDebugAllocationRemove(isa, self);
 
376
#endif
 
377
  isa = [GSDictionary class];
 
378
#ifndef NDEBUG
 
379
  GSDebugAllocationAdd(isa, self);
 
380
#endif
 
381
  return self;
 
382
}
 
383
 
286
384
- (void) setObject: (id)anObject forKey: (id)aKey
287
385
{
288
386
  GSIMapNode    node;
289
387
 
290
388
  if (aKey == nil)
291
389
    {
292
 
      [NSException raise: NSInvalidArgumentException
293
 
                  format: @"Tried to add nil key to dictionary"];
 
390
      NSException       *e;
 
391
 
 
392
      e = [NSException exceptionWithName: NSInvalidArgumentException
 
393
                                  reason: @"Tried to add nil key to dictionary"
 
394
                                userInfo: self];
 
395
      [e raise];
294
396
    }
295
397
  if (anObject == nil)
296
398
    {
297
 
      [NSException raise: NSInvalidArgumentException
298
 
                  format: @"Tried to add nil value to dictionary"];
 
399
      NSException       *e;
 
400
      NSString          *s;
 
401
 
 
402
      s = [NSString stringWithFormat:
 
403
        @"Tried to add nil value for key '%@' to dictionary", aKey];
 
404
      e = [NSException exceptionWithName: NSInvalidArgumentException
 
405
                                  reason: s
 
406
                                userInfo: self];
 
407
      [e raise];
299
408
    }
300
409
  node = GSIMapNodeForKey(&map, (GSIMapKey)aKey);
301
410
  if (node)
319
428
{
320
429
  if (aKey == nil)
321
430
    {
322
 
      NSWarnMLog(@"attempt to remove nil key");
 
431
      NSWarnMLog(@"attempt to remove nil key from dictionary %@", self);
323
432
      return;
324
433
    }
325
434
  GSIMapRemoveKey(&map, (GSIMapKey)aKey);
350
459
 
351
460
- (void) dealloc
352
461
{
 
462
  GSIMapEndEnumerator(&enumerator);
353
463
  RELEASE(dictionary);
354
464
  [super dealloc];
355
465
}