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

« back to all changes in this revision

Viewing changes to Source/NSArray.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:
1
1
/** NSArray - Array object to hold other objects.
2
2
   Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
3
 
   
 
3
 
4
4
   Written by:  Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
5
5
   From skeleton by:  Adam Fedor <fedor@boulder.colorado.edu>
6
6
   Created: March 1995
7
 
   
 
7
 
8
8
   Rewrite by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
9
 
   January 1998 - new methods and changes as documented for Rhapsody plus 
 
9
   January 1998 - new methods and changes as documented for Rhapsody plus
10
10
   changes of array indices to type unsigned, plus major efficiency hacks.
11
11
 
12
12
   This file is part of the GNUstep Base Library.
13
 
   
 
13
 
14
14
   This library is free software; you can redistribute it and/or
15
15
   modify it under the terms of the GNU Library General Public
16
16
   License as published by the Free Software Foundation; either
17
17
   version 2 of the License, or (at your option) any later version.
18
 
   
 
18
 
19
19
   This library is distributed in the hope that it will be useful,
20
20
   but WITHOUT ANY WARRANTY; without even the implied warranty of
21
21
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22
22
   Library General Public License for more details.
23
 
   
 
23
 
24
24
   You should have received a copy of the GNU Library General Public
25
25
   License along with this library; if not, write to the Free
26
26
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
27
27
 
28
28
   <title>NSArray class reference</title>
29
 
   $Date: 2002/03/13 09:58:43 $ $Revision: 1.107 $
 
29
   $Date: 2005/02/22 11:22:43 $ $Revision: 1.144 $
30
30
   */
31
31
 
32
 
#include <config.h>
33
 
#include <base/behavior.h>
34
 
#include <Foundation/NSArray.h>
35
 
#include <Foundation/NSCoder.h>
36
 
#include <Foundation/NSString.h>
37
 
#include <Foundation/NSRange.h>
 
32
#include "config.h"
 
33
#include "Foundation/NSArray.h"
 
34
#include "Foundation/NSCoder.h"
 
35
#include "Foundation/NSData.h"
 
36
#include "Foundation/NSString.h"
 
37
#include "Foundation/NSRange.h"
38
38
#include <limits.h>
39
 
#include <Foundation/NSUtilities.h>
40
 
#include <Foundation/NSException.h>
41
 
#include <Foundation/NSAutoreleasePool.h>
42
 
#include <Foundation/NSThread.h>
43
 
#include <Foundation/NSMapTable.h>
44
 
#include <Foundation/NSLock.h>
45
 
#include <Foundation/NSDebug.h>
 
39
#include "Foundation/NSUtilities.h"
 
40
#include "Foundation/NSException.h"
 
41
#include "Foundation/NSAutoreleasePool.h"
 
42
#include "Foundation/NSThread.h"
 
43
#include "Foundation/NSMapTable.h"
 
44
#include "Foundation/NSLock.h"
 
45
#include "Foundation/NSDebug.h"
 
46
#include "Foundation/NSValue.h"
 
47
#include "Foundation/NSNull.h"
 
48
// For private method _decodeArrayOfObjectsForKey:
 
49
#include "Foundation/NSKeyedArchiver.h"
 
50
#include "GNUstepBase/GSCategories.h"
46
51
#include "GSPrivate.h"
47
52
 
 
53
extern BOOL     GSMacOSXCompatiblePropertyLists(void);
 
54
extern void     GSPropertyListMake(id,NSDictionary*,BOOL,BOOL,unsigned,id*);
 
55
 
48
56
@class NSArrayEnumerator;
49
57
@class NSArrayEnumeratorReverse;
50
58
 
64
72
static NSMapTable               *placeholderMap;
65
73
static NSLock                   *placeholderLock;
66
74
 
67
 
@interface      NSArray (GSPrivate)
68
 
- (id) _initWithObjects: firstObject rest: (va_list) ap;
69
 
@end
70
 
 
71
 
 
 
75
/**
 
76
 * A simple, low overhead, ordered container for objects.  All the objects
 
77
 * in the container are retained by it.  The container may not contain nil
 
78
 * (though it may contain [NSNull+null]).
 
79
 */
72
80
@implementation NSArray
73
81
 
74
82
static SEL      addSel;
158
166
    }
159
167
}
160
168
 
 
169
/**
 
170
 * Returns an empty autoreleased array.
 
171
 */
161
172
+ (id) array
162
173
{
163
174
  id    o;
167
178
  return AUTORELEASE(o);
168
179
}
169
180
 
 
181
/**
 
182
 * Returns a new autoreleased NSArray instance containing all the objects from
 
183
 * array, in the same order as the original.
 
184
 */
170
185
+ (id) arrayWithArray: (NSArray*)array
171
186
{
172
187
  id    o;
176
191
  return AUTORELEASE(o);
177
192
}
178
193
 
 
194
/**
 
195
 * Returns an autoreleased array based upon the file.  The new array is
 
196
 * created using +allocWithZone: and initialised using the
 
197
 * -initWithContentsOfFile: method. See the documentation for those
 
198
 * methods for more detail.
 
199
 */
179
200
+ (id) arrayWithContentsOfFile: (NSString*)file
180
201
{
181
202
  id    o;
185
206
  return AUTORELEASE(o);
186
207
}
187
208
 
 
209
/**
 
210
 * Returns an autoreleased array from the contenta of aURL.  The new array is
 
211
 * created using +allocWithZone: and initialised using the
 
212
 * -initWithContentsOfURL: method. See the documentation for those
 
213
 * methods for more detail.
 
214
 */
 
215
+ (id) arrayWithContentsOfURL: (NSURL*)aURL
 
216
{
 
217
  id    o;
 
218
 
 
219
  o = [self allocWithZone: NSDefaultMallocZone()];
 
220
  o = [o initWithContentsOfURL: aURL];
 
221
  return AUTORELEASE(o);
 
222
}
 
223
 
 
224
/**
 
225
 * Returns an autoreleased array containing anObject.
 
226
 */
188
227
+ (id) arrayWithObject: (id)anObject
189
228
{
190
229
  id    o;
194
233
  return AUTORELEASE(o);
195
234
}
196
235
 
 
236
/**
 
237
 * Returns an autoreleased array containing the list
 
238
 * of objects, preserving order.
 
239
 */
197
240
+ (id) arrayWithObjects: firstObject, ...
198
241
{
199
 
  va_list ap;
200
 
  va_start(ap, firstObject);
201
 
  self = [[self allocWithZone: NSDefaultMallocZone()]
202
 
    _initWithObjects: firstObject rest: ap];
203
 
  va_end(ap);
204
 
  return AUTORELEASE(self);
 
242
  id    a = [self allocWithZone: NSDefaultMallocZone()];
 
243
 
 
244
  GS_USEIDLIST(firstObject,
 
245
    a = [a initWithObjects: __objects count: __count]);
 
246
  return AUTORELEASE(a);
205
247
}
206
248
 
 
249
/**
 
250
 * Returns an autoreleased array containing the specified
 
251
 * objects, preserving order.
 
252
 */
207
253
+ (id) arrayWithObjects: (id*)objects count: (unsigned)count
208
254
{
209
255
  return AUTORELEASE([[self allocWithZone: NSDefaultMallocZone()]
210
256
    initWithObjects: objects count: count]);
211
257
}
212
258
 
 
259
/**
 
260
 * Returns an autoreleased array formed from the contents of
 
261
 * the receiver and adding anObject as the last item.
 
262
 */
213
263
- (NSArray*) arrayByAddingObject: (id)anObject
214
264
{
215
265
  id na;
216
266
  unsigned      c = [self count];
217
 
 
 
267
 
218
268
  if (anObject == nil)
219
269
    [NSException raise: NSInvalidArgumentException
220
270
                format: @"Attempt to add nil to an array"];
221
271
  if (c == 0)
222
 
    na = [[GSArrayClass allocWithZone: NSDefaultMallocZone()]
223
 
      initWithObjects: &anObject count: 1];
 
272
    {
 
273
      na = [[GSArrayClass allocWithZone: NSDefaultMallocZone()]
 
274
        initWithObjects: &anObject count: 1];
 
275
    }
224
276
  else
225
277
    {
226
 
      id        objects[c+1];
 
278
      GS_BEGINIDBUF(objects, c+1);
227
279
 
228
280
      [self getObjects: objects];
229
281
      objects[c] = anObject;
230
282
      na = [[GSArrayClass allocWithZone: NSDefaultMallocZone()]
231
283
        initWithObjects: objects count: c+1];
 
284
 
 
285
      GS_ENDIDBUF();
232
286
    }
233
287
  return AUTORELEASE(na);
234
288
}
235
289
 
 
290
/**
 
291
 * Returns a new array which is the concatenation of self and
 
292
 * otherArray (in this precise order).
 
293
 */
236
294
- (NSArray*) arrayByAddingObjectsFromArray: (NSArray*)anotherArray
237
295
{
238
296
  id            na;
240
298
 
241
299
  c = [self count];
242
300
  l = [anotherArray count];
 
301
 
243
302
  {
244
 
    id  objects[c+l];
 
303
    GS_BEGINIDBUF(objects, c+l);
245
304
 
246
305
    [self getObjects: objects];
247
306
    [anotherArray getObjects: &objects[c]];
248
307
    na = [NSArrayClass arrayWithObjects: objects count: c+l];
 
308
 
 
309
    GS_ENDIDBUF();
249
310
  }
 
311
 
250
312
  return na;
251
313
}
252
314
 
 
315
/**
 
316
 * Returns the abstract class ... arrays are coded as abstract arrays.
 
317
 */
253
318
- (Class) classForCoder
254
319
{
255
320
  return NSArrayClass;
256
321
}
257
322
 
258
 
- (BOOL) containsObject: anObject
 
323
/**
 
324
 * Returns YES if anObject belongs to self. No otherwise.<br />
 
325
 * The -isEqual: method of anObject is used to test for equality.
 
326
 */
 
327
- (BOOL) containsObject: (id)anObject
259
328
{
260
329
  return ([self indexOfObject: anObject] != NSNotFound);
261
330
}
262
331
 
 
332
/**
 
333
 * Returns a new copy of the receiver.<br />
 
334
 * The default abstract implementation of a copy is to use the
 
335
 * -initWithArray:copyItems: method with the flag set to YES.<br />
 
336
 * Immutable subclasses generally simply retain and return the receiver.
 
337
 */
263
338
- (id) copyWithZone: (NSZone*)zone
264
339
{
265
 
  return RETAIN(self);
 
340
  NSArray       *copy = [NSArrayClass allocWithZone: zone];
 
341
 
 
342
  return [copy initWithArray: self copyItems: YES];
266
343
}
267
344
 
 
345
/** <override-subclass />
 
346
 * Returns the number of elements contained in the receiver.
 
347
 */
268
348
- (unsigned) count
269
349
{
270
350
  [self subclassResponsibility: _cmd];
271
351
  return 0;
272
352
}
273
353
 
 
354
/**
 
355
 * Encodes the receiver for storing to archive or sending over an
 
356
 * [NSConnection].
 
357
 */
274
358
- (void) encodeWithCoder: (NSCoder*)aCoder
275
359
{
276
360
  unsigned      count = [self count];
277
361
 
278
 
  [aCoder encodeValueOfObjCType: @encode(unsigned)
279
 
                             at: &count];
280
 
 
281
 
  if (count > 0)
282
 
    {
283
 
      id        a[count];
284
 
 
285
 
      [self getObjects: a];
286
 
      [aCoder encodeArrayOfObjCType: @encode(id)
287
 
                              count: count
288
 
                                 at: a];
 
362
  if ([aCoder allowsKeyedCoding])
 
363
    {
 
364
      /* HACK ... MacOS-X seems to code differently if the coder is an
 
365
       * actual instance of NSKeyedArchiver
 
366
       */
 
367
      if ([aCoder class] == [NSKeyedArchiver class])
 
368
        {
 
369
          [(NSKeyedArchiver*)aCoder _encodeArrayOfObjects: self
 
370
                                                   forKey: @"NS.objects"];
 
371
        }
 
372
      else
 
373
        {
 
374
          unsigned      i;
 
375
 
 
376
          for (i = 0; i < count; i++)
 
377
            {
 
378
              NSString  *key;
 
379
 
 
380
              key = [NSString stringWithFormat: @"NS.object.%u", i];
 
381
              [(NSKeyedArchiver*)aCoder encodeObject: [self objectAtIndex: i]
 
382
                                              forKey: key];
 
383
            }
 
384
        }
 
385
    }
 
386
  else
 
387
    {
 
388
      [aCoder encodeValueOfObjCType: @encode(unsigned)
 
389
                                 at: &count];
 
390
 
 
391
      if (count > 0)
 
392
        {
 
393
          GS_BEGINIDBUF(a, count);
 
394
 
 
395
          [self getObjects: a];
 
396
          [aCoder encodeArrayOfObjCType: @encode(id)
 
397
                                  count: count
 
398
                                     at: a];
 
399
          GS_ENDIDBUF();
 
400
        }
289
401
    }
290
402
}
291
403
 
 
404
/**
 
405
 * Copies the objects from the receiver to aBuffer, which must be
 
406
 * an area of memory large enough to hold them.
 
407
 */
292
408
- (void) getObjects: (id*)aBuffer
293
409
{
294
410
  unsigned i, c = [self count];
298
414
    aBuffer[i] = (*get)(self, oaiSel, i);
299
415
}
300
416
 
 
417
/**
 
418
 * Copies the objects from the range aRange of the receiver to aBuffer,
 
419
 * which must be an area of memory large enough to hold them.
 
420
 */
301
421
- (void) getObjects: (id*)aBuffer range: (NSRange)aRange
302
422
{
303
423
  unsigned i, j = 0, c = [self count], e = aRange.location + aRange.length;
309
429
    aBuffer[j++] = (*get)(self, oaiSel, i);
310
430
}
311
431
 
 
432
/**
 
433
 * Returns the same value as -count
 
434
 */
312
435
- (unsigned) hash
313
436
{
314
437
  return [self count];
315
438
}
316
439
 
317
 
- (unsigned) indexOfObjectIdenticalTo: anObject
 
440
/**
 
441
 * Returns the index of the specified object in the receiver, or
 
442
 * NSNotFound if the object is not present.
 
443
 */
 
444
- (unsigned) indexOfObjectIdenticalTo: (id)anObject
318
445
{
319
446
  unsigned c = [self count];
320
447
 
330
457
  return NSNotFound;
331
458
}
332
459
 
 
460
/**
 
461
 * Returns the index of the specified object in the range of the receiver,
 
462
 * or NSNotFound if the object is not present.
 
463
 */
333
464
- (unsigned) indexOfObjectIdenticalTo: anObject inRange: (NSRange)aRange
334
465
{
335
466
  unsigned i, e = aRange.location + aRange.length, c = [self count];
343
474
  return NSNotFound;
344
475
}
345
476
 
346
 
/* Inefficient, should be overridden. */
 
477
/**
 
478
 * Returns the index of the first object found in the receiver
 
479
 * which is equal to anObject (using anObject's -isEqual: method).
 
480
 * Returns NSNotFound on failure.
 
481
 */
347
482
- (unsigned) indexOfObject: (id)anObject
348
483
{
349
484
  unsigned      c = [self count];
362
497
  return NSNotFound;
363
498
}
364
499
 
365
 
/* Inefficient, should be overridden. */
 
500
/**
 
501
 * Returns the index of the first object found in aRange of receiver
 
502
 * which is equal to anObject (using anObject's -isEqual: method).
 
503
 * Returns NSNotFound on failure.
 
504
 */
366
505
- (unsigned) indexOfObject: (id)anObject inRange: (NSRange)aRange
367
506
{
368
507
  unsigned i, e = aRange.location + aRange.length, c = [self count];
380
519
  return NSNotFound;
381
520
}
382
521
 
 
522
/**
 
523
 * <p>In MacOS-X class clusters do not have designated initialisers,
 
524
 * and there is a general rule that -init is treated as the designated
 
525
 * initialiser of the class cluster, but that other intitialisers
 
526
 * may not work s expected an would need to be individually overridden
 
527
 * in any subclass.
 
528
 * </p>
 
529
 * <p>GNUstep tries to make it easier to subclass a class cluster,
 
530
 * by making class clusters follow the same convention as normal
 
531
 * classes, so the designated initialiser is the <em>richest</em>
 
532
 * initialiser.  This means that all other initialisers call the
 
533
 * documented designated initialiser (which calls -init only for
 
534
 * MacOS-X compatibility), and anyone writing a subclass only needs
 
535
 * to override that one initialiser in order to have all the other
 
536
 * ones work.
 
537
 * </p>
 
538
 * <p>For MacOS-X compatibility, you may also need to override various
 
539
 * other initialisers.  Exactly which ones, you will need to determine
 
540
 * by trial on a MacOS-X system ... and may vary between releases of
 
541
 * MacOS-X.  So to be safe, on MacOS-X you probably need to re-implement
 
542
 * <em>all</em> the class cluster initialisers you might use in conjunction
 
543
 * with your subclass.
 
544
 * </p>
 
545
 */
383
546
- (id) init
384
547
{
385
 
  return [self initWithObjects: (id*)0 count: 0];
386
 
}
387
 
 
 
548
  self = [super init];
 
549
  return self;
 
550
}
 
551
 
 
552
/**
 
553
 * Initialize the receiver with the contents of array.
 
554
 * The order of array is preserved.<br />
 
555
 * If shouldCopy is YES then the objects are copied
 
556
 * rather than simply retained.<br />
 
557
 * Invokes -initWithObjects:count:
 
558
 */
 
559
- (id) initWithArray: (NSArray*)array copyItems: (BOOL)shouldCopy
 
560
{
 
561
  unsigned      c = [array count];
 
562
  GS_BEGINIDBUF(objects, c);
 
563
 
 
564
  [array getObjects: objects];
 
565
  if (shouldCopy == YES)
 
566
    {
 
567
      unsigned  i;
 
568
 
 
569
      for (i = 0; i < c; i++)
 
570
        {
 
571
          objects[i] = [objects[i] copy];
 
572
        }
 
573
      self = [self initWithObjects: objects count: c];
 
574
#if GS_WITH_GC == 0
 
575
      while (i > 0)
 
576
        {
 
577
          [objects[--i] release];
 
578
        }
 
579
#endif
 
580
    }
 
581
  else
 
582
    {
 
583
      self = [self initWithObjects: objects count: c];
 
584
    }
 
585
  GS_ENDIDBUF();
 
586
  return self;
 
587
}
 
588
 
 
589
/**
 
590
 * Initialize the receiver with the contents of array.
 
591
 * The order of array is preserved.<br />
 
592
 * Invokes -initWithObjects:count:
 
593
 */
388
594
- (id) initWithArray: (NSArray*)array
389
595
{
390
 
  unsigned c;
391
 
 
392
 
  c = [array count];
393
 
  {
394
 
    id  objects[c];
395
 
 
396
 
    [array getObjects: objects];
397
 
    self = [self initWithObjects: objects count: c];
398
 
  }
 
596
  unsigned      c = [array count];
 
597
  GS_BEGINIDBUF(objects, c);
 
598
 
 
599
  [array getObjects: objects];
 
600
  self = [self initWithObjects: objects count: c];
 
601
  GS_ENDIDBUF();
399
602
  return self;
400
603
}
401
604
 
 
605
/**
 
606
 * Initialize the array by decoding from an archive.<br />
 
607
 * Invokes -initWithObjects:count:
 
608
 */
402
609
- (id) initWithCoder: (NSCoder*)aCoder
403
610
{
404
 
  unsigned    count;
405
 
 
406
 
  [aCoder decodeValueOfObjCType: @encode(unsigned)
407
 
                             at: &count];
408
 
  if (count > 0)
 
611
  if ([aCoder allowsKeyedCoding])
409
612
    {
410
 
      id        contents[count];
411
 
 
412
 
      [aCoder decodeArrayOfObjCType: @encode(id)
413
 
                              count: count
414
 
                                 at: contents];
415
 
      return [self initWithObjects: contents count: count];
 
613
      id        array;
 
614
 
 
615
      array = [(NSKeyedUnarchiver*)aCoder _decodeArrayOfObjectsForKey:
 
616
                                                @"NS.objects"];
 
617
      if (array == nil)
 
618
        {
 
619
          unsigned      i = 0;
 
620
          NSString      *key;
 
621
          id            val;
 
622
 
 
623
          array = [NSMutableArray arrayWithCapacity: 2];
 
624
          key = [NSString stringWithFormat: @"NS.object.%u", i];
 
625
          val = [(NSKeyedUnarchiver*)aCoder decodeObjectForKey: key];
 
626
 
 
627
          while (val != nil)
 
628
            {
 
629
              [array addObject: val];
 
630
              i++;
 
631
              key = [NSString stringWithFormat: @"NS.object.%u", i];
 
632
              val = [(NSKeyedUnarchiver*)aCoder decodeObjectForKey: key];
 
633
            }
 
634
        }
 
635
 
 
636
      self = [self initWithArray: array];
416
637
    }
417
638
  else
418
 
    return [self initWithObjects: 0 count: 0];
 
639
    {
 
640
      unsigned    count;
 
641
 
 
642
      [aCoder decodeValueOfObjCType: @encode(unsigned)
 
643
                                 at: &count];
 
644
      if (count > 0)
 
645
        {
 
646
          GS_BEGINIDBUF(contents, count);
 
647
 
 
648
          [aCoder decodeArrayOfObjCType: @encode(id)
 
649
                  count: count
 
650
                  at: contents];
 
651
          self = [self initWithObjects: contents count: count];
 
652
#if GS_WITH_GC == 0
 
653
          while (count-- > 0)
 
654
            {
 
655
              [contents[count] release];
 
656
            }
 
657
#endif
 
658
          GS_ENDIDBUF();
 
659
        }
 
660
      else
 
661
        {
 
662
          self = [self initWithObjects: 0 count: 0];
 
663
        }
 
664
    }
 
665
  return self;
419
666
}
420
667
 
 
668
/**
 
669
 * <p>Initialises the array with the contents of the specified file,
 
670
 * which must contain an array in property-list format.
 
671
 * </p>
 
672
 * <p>In GNUstep, the property-list format may be either the OpenStep
 
673
 * format (ASCII data), or the MacOS-X format (UTF-8 XML data) ... this
 
674
 * method will recognise which it is.
 
675
 * </p>
 
676
 * <p>If there is a failure to load the file for any reason, the receiver
 
677
 * will be released, the method will return nil, and a warning may be logged.
 
678
 * </p>
 
679
 * <p>Works by invoking [NSString-initWithContentsOfFile:] and
 
680
 * [NSString-propertyList] then checking that the result is an array.
 
681
 * </p>
 
682
 */
421
683
- (id) initWithContentsOfFile: (NSString*)file
422
684
{
423
685
  NSString      *myString;
424
686
 
425
687
  myString = [[NSString allocWithZone: NSDefaultMallocZone()]
426
688
    initWithContentsOfFile: file];
427
 
  if (myString)
428
 
    {
429
 
      id result;
430
 
 
431
 
      NS_DURING
432
 
        {
433
 
          result = [myString propertyList];
434
 
        }
435
 
      NS_HANDLER
436
 
        {
437
 
          result = nil;
438
 
        }
439
 
      NS_ENDHANDLER
440
 
      RELEASE(myString);
441
 
      if ([result isKindOfClass: NSArrayClass])
442
 
        {
443
 
          self = [self initWithArray: result];
444
 
          return self;
445
 
        }
446
 
    }
447
 
  NSWarnMLog(@"Contents of file '%@' does not contain an array", file);
448
 
  RELEASE(self);
449
 
  return nil;
450
 
}
451
 
 
452
 
/* This is the designated initializer for NSArray. */
 
689
  if (myString == nil)
 
690
    {
 
691
      DESTROY(self);
 
692
    }
 
693
  else
 
694
    {
 
695
      id result;
 
696
 
 
697
      NS_DURING
 
698
        {
 
699
          result = [myString propertyList];
 
700
        }
 
701
      NS_HANDLER
 
702
        {
 
703
          result = nil;
 
704
        }
 
705
      NS_ENDHANDLER
 
706
      RELEASE(myString);
 
707
      if ([result isKindOfClass: NSArrayClass])
 
708
        {
 
709
          self = [self initWithArray: result];
 
710
        }
 
711
      else
 
712
        {
 
713
          NSWarnMLog(@"Contents of file '%@' does not contain an array", file);
 
714
          DESTROY(self);
 
715
        }
 
716
    }
 
717
  return self;
 
718
}
 
719
 
 
720
/**
 
721
 * <p>Initialises the array with the contents of the specified URL,
 
722
 * which must contain an array in property-list format.
 
723
 * </p>
 
724
 * <p>In GNUstep, the property-list format may be either the OpenStep
 
725
 * format (ASCII data), or the MacOS-X format (URF8 XML data) ... this
 
726
 * method will recognise which it is.
 
727
 * </p>
 
728
 * <p>If there is a failure to load the URL for any reason, the receiver
 
729
 * will be released, the method will return nil, and a warning may be logged.
 
730
 * </p>
 
731
 * <p>Works by invoking [NSString-initWithContentsOfURL:] and
 
732
 * [NSString-propertyList] then checking that the result is an array.
 
733
 * </p>
 
734
 */
 
735
- (id) initWithContentsOfURL: (NSURL*)aURL
 
736
{
 
737
  NSString      *myString;
 
738
 
 
739
  myString = [[NSString allocWithZone: NSDefaultMallocZone()]
 
740
    initWithContentsOfURL: aURL];
 
741
  if (myString == nil)
 
742
    {
 
743
      DESTROY(self);
 
744
    }
 
745
  else
 
746
    {
 
747
      id result;
 
748
 
 
749
      NS_DURING
 
750
        {
 
751
          result = [myString propertyList];
 
752
        }
 
753
      NS_HANDLER
 
754
        {
 
755
          result = nil;
 
756
        }
 
757
      NS_ENDHANDLER
 
758
      RELEASE(myString);
 
759
      if ([result isKindOfClass: NSArrayClass])
 
760
        {
 
761
          self = [self initWithArray: result];
 
762
        }
 
763
      else
 
764
        {
 
765
          NSWarnMLog(@"Contents of URL '%@' does not contain an array", aURL);
 
766
          DESTROY(self);
 
767
        }
 
768
    }
 
769
  return self;
 
770
}
 
771
 
 
772
/** <init /> <override-subclass />
 
773
 * This should initialize the array with count (may be zero) objects.<br />
 
774
 * Retains each object placed in the array.<br />
 
775
 * Calls -init (which does nothing but maintain MacOS-X compatibility),
 
776
 * and needs to be re-implemented in subclasses in order to have all
 
777
 * other initialisers work.
 
778
 */
453
779
- (id) initWithObjects: (id*)objects count: (unsigned)count
454
780
{
455
 
  [self subclassResponsibility: _cmd];
456
 
  return nil;
457
 
}
458
 
 
459
 
- (id) _initWithObjects: firstObject rest: (va_list) ap
460
 
{
461
 
  register      unsigned                i;
462
 
  register      unsigned                curSize;
463
 
  auto          unsigned                prevSize;
464
 
  auto          unsigned                newSize;
465
 
  auto          id                      *objsArray;
466
 
  auto          id                      tmpId;
467
 
 
468
 
  /*    Do initial allocation.  */
469
 
  prevSize = 3;
470
 
  curSize  = 5;
471
 
  objsArray = (id*)NSZoneMalloc(NSDefaultMallocZone(), sizeof(id) * curSize);
472
 
  tmpId = firstObject;
473
 
 
474
 
  /*    Loop through adding objects to array until a nil is
475
 
   *    found.
476
 
   */
477
 
  for (i = 0; tmpId != nil; i++)
478
 
    {
479
 
      /*        Put id into array.      */
480
 
      objsArray[i] = tmpId;
481
 
 
482
 
      /*        If the index equals the current size, increase size.    */
483
 
      if (i == curSize - 1)
484
 
        {
485
 
          /*    Fibonacci series.  Supposedly, for this application,
486
 
           *    the fibonacci series will be more memory efficient.
487
 
           */
488
 
          newSize  = prevSize + curSize;
489
 
          prevSize = curSize;
490
 
          curSize  = newSize;
491
 
 
492
 
          /*    Reallocate object array.        */
493
 
          objsArray = (id*)NSZoneRealloc(NSDefaultMallocZone(), objsArray,
494
 
            sizeof(id) * curSize);
495
 
        }
496
 
      tmpId = va_arg(ap, id);
497
 
    }
498
 
  va_end( ap );
499
 
 
500
 
  /*    Put object ids into NSArray.    */
501
 
  self = [self initWithObjects: objsArray count: i];
502
 
  NSZoneFree(NSDefaultMallocZone(), objsArray);
503
 
  return( self );
504
 
}
505
 
 
 
781
  self = [self init];
 
782
  return self;
 
783
}
 
784
 
 
785
/**
 
786
 * Initialize the array the list of objects.
 
787
 * <br />May change the value of self before returning it.
 
788
 */
506
789
- (id) initWithObjects: firstObject, ...
507
790
{
508
 
  va_list ap;
509
 
  va_start(ap, firstObject);
510
 
  self = [self _initWithObjects: firstObject rest: ap];
511
 
  va_end(ap);
 
791
  GS_USEIDLIST(firstObject,
 
792
    self = [self initWithObjects: __objects count: __count]);
512
793
  return self;
513
794
}
514
795
 
 
796
/**
 
797
 * Returns an NSMutableArray instance containing the same objects as
 
798
 * the receiver.<br />
 
799
 * The default implementation does this by calling the
 
800
 * -initWithArray:copyItems: method on a newly created object,
 
801
 * and passing it NO to tell it just to retain the items.
 
802
 */
515
803
- (id) mutableCopyWithZone: (NSZone*)zone
516
804
{
517
 
  return [[GSMutableArrayClass allocWithZone: zone] 
518
 
    initWithArray: self];
 
805
  NSMutableArray        *copy = [NSMutableArrayClass allocWithZone: zone];
 
806
 
 
807
  return [copy initWithArray: self copyItems: NO];
519
808
}
520
809
 
 
810
/** <override-subclass />
 
811
 * Returns the object at the specified index.
 
812
 * Raises an exception of the index is beyond the array.
 
813
 */
521
814
- (id) objectAtIndex: (unsigned)index
522
815
{
523
816
  [self subclassResponsibility: _cmd];
533
826
  return NO;
534
827
}
535
828
 
 
829
/**
 
830
 * Returns YES if the receiver is equal to otherArray, NO otherwise.
 
831
 */
536
832
- (BOOL) isEqualToArray: (NSArray*)otherArray
537
833
{
538
834
  unsigned i, c;
539
 
 
 
835
 
540
836
  if (self == (id)otherArray)
541
837
    return YES;
542
838
  c = [self count];
554
850
  return YES;
555
851
}
556
852
 
 
853
/**
 
854
 * Returns the last object in the receiver, or nil if the receiver is empty.
 
855
 */
557
856
- (id) lastObject
558
857
{
559
858
  unsigned count = [self count];
562
861
  return [self objectAtIndex: count-1];
563
862
}
564
863
 
 
864
/**
 
865
 * Makes each object in the array perform aSelector.<br />
 
866
 * This is done sequentially from the first to the last object.
 
867
 */
565
868
- (void) makeObjectsPerformSelector: (SEL)aSelector
566
869
{
567
 
  unsigned i = [self count];
 
870
  unsigned      c = [self count];
568
871
 
569
 
  if (i > 0)
 
872
  if (c > 0)
570
873
    {
571
874
      IMP       get = [self methodForSelector: oaiSel];
 
875
      unsigned  i = 0;
572
876
 
573
 
      while (i-- > 0)
574
 
        [(*get)(self, oaiSel, i) performSelector: aSelector];
 
877
      while (i < c)
 
878
        {
 
879
          [(*get)(self, oaiSel, i++) performSelector: aSelector];
 
880
        }
575
881
    }
576
882
}
577
883
 
 
884
/**
 
885
 * Obsolete version of -makeObjectsPerformSelector:
 
886
 */
578
887
- (void) makeObjectsPerform: (SEL)aSelector
579
888
{
580
889
   [self makeObjectsPerformSelector: aSelector];
581
890
}
582
891
 
583
 
- (void) makeObjectsPerformSelector: (SEL)aSelector withObject: (id) arg
 
892
/**
 
893
 * Makes each object in the array perform aSelector with arg.<br />
 
894
 * This is done sequentially from the first to the last object.
 
895
 */
 
896
- (void) makeObjectsPerformSelector: (SEL)aSelector withObject: (id)arg
584
897
{
585
 
  unsigned i = [self count];
 
898
  unsigned      c = [self count];
586
899
 
587
 
  if (i > 0)
 
900
  if (c > 0)
588
901
    {
589
902
      IMP       get = [self methodForSelector: oaiSel];
 
903
      unsigned  i = 0;
590
904
 
591
 
      while (i-- > 0)
592
 
        [(*get)(self, oaiSel, i) performSelector: aSelector withObject: arg];
 
905
      while (i < c)
 
906
        {
 
907
          [(*get)(self, oaiSel, i++) performSelector: aSelector
 
908
                                          withObject: arg];
 
909
        }
593
910
    }
594
911
}
595
912
 
 
913
/**
 
914
 * Obsolete version of -makeObjectsPerformSelector:withObject:
 
915
 */
596
916
- (void) makeObjectsPerform: (SEL)aSelector withObject: (id)argument
597
917
{
598
918
   [self makeObjectsPerformSelector: aSelector withObject: argument];
599
919
}
600
920
 
601
 
static int compare(id elem1, id elem2, void* context)
 
921
static NSComparisonResult
 
922
compare(id elem1, id elem2, void* context)
602
923
{
603
 
  return (int)[elem1 performSelector: (SEL)context withObject: elem2];
 
924
  NSComparisonResult (*imp)(id, SEL, id);
 
925
 
 
926
  if (context == 0)
 
927
    {
 
928
      [NSException raise: NSInvalidArgumentException
 
929
                   format: @"compare null selector given"];
 
930
    }
 
931
 
 
932
  imp = (NSComparisonResult (*)(id, SEL, id))
 
933
    [elem1 methodForSelector: context];
 
934
 
 
935
  if (imp == NULL)
 
936
    {
 
937
      [NSException raise: NSGenericException
 
938
                  format: @"invalid selector passed to compare"];
 
939
    }
 
940
 
 
941
  return (*imp)(elem1, context, elem2);
604
942
}
605
943
 
 
944
/**
 
945
 * Returns an autoreleased array in which the objects are ordered
 
946
 * according to a sort with comparator.
 
947
 */
606
948
- (NSArray*) sortedArrayUsingSelector: (SEL)comparator
607
949
{
608
950
  return [self sortedArrayUsingFunction: compare context: (void *)comparator];
609
951
}
610
952
 
611
 
- (NSArray*) sortedArrayUsingFunction: (int(*)(id,id,void*))comparator 
 
953
/**
 
954
 * Returns an autoreleased array in which the objects are ordered
 
955
 * according to a sort with comparator.  This invokes
 
956
 * -sortedArrayUsingFunction:context:hint: with a nil hint.
 
957
 */
 
958
- (NSArray*) sortedArrayUsingFunction: (NSComparisonResult(*)(id,id,void*))comparator
612
959
   context: (void*)context
613
960
{
614
961
  return [self sortedArrayUsingFunction: comparator context: context hint: nil];
615
962
}
616
963
 
 
964
/**
 
965
 * Subclasses may provide a hint for sorting ...  The default GNUstep
 
966
 * implementation just returns nil.
 
967
 */
617
968
- (NSData*) sortedArrayHint
618
969
{
619
970
  return nil;
620
971
}
621
972
 
622
 
- (NSArray*) sortedArrayUsingFunction: (int(*)(id,id,void*))comparator 
 
973
/**
 
974
 * Returns an autoreleased array in which the objects are ordered
 
975
 * according to a sort with comparator, where the comparator function
 
976
 * is passed two objects to compare, and the context as the third
 
977
 * argument.  The hint argument is currently ignored, and may be nil.
 
978
 */
 
979
- (NSArray*) sortedArrayUsingFunction: (NSComparisonResult(*)(id,id,void*))comparator
623
980
   context: (void*)context
624
981
   hint: (NSData*)hint
625
982
{
626
983
  NSMutableArray        *sortedArray;
627
 
  NSArray               *result;
628
984
 
629
985
  sortedArray = [[NSMutableArrayClass allocWithZone:
630
 
    NSDefaultMallocZone()] initWithArray: self];
 
986
    NSDefaultMallocZone()] initWithArray: self copyItems: NO];
631
987
  [sortedArray sortUsingFunction: comparator context: context];
632
 
  result = [NSArrayClass arrayWithArray: sortedArray];
633
 
  RELEASE(sortedArray);
634
 
  return result;
 
988
 
 
989
  return AUTORELEASE([sortedArray makeImmutableCopyOnFail: NO]);
635
990
}
636
991
 
 
992
/**
 
993
 * Returns a string formed by concatenating the objects in the receiver,
 
994
 * with the specified separator string inserted between each part.
 
995
 */
637
996
- (NSString*) componentsJoinedByString: (NSString*)separator
638
997
{
639
 
  unsigned i, c = [self count];
640
 
  id s = [NSMutableString stringWithCapacity: 2]; /* arbitrary capacity */
641
 
  
642
 
  if (!c)
643
 
    return s;
644
 
  [s appendString: [[self objectAtIndex: 0] description]];
645
 
  for (i = 1; i < c; i++)
 
998
  unsigned int          c = [self count];
 
999
  NSMutableString       *s = [[NSMutableString alloc] initWithCapacity: c];
 
1000
 
 
1001
  if (c > 0)
646
1002
    {
647
 
      [s appendString: separator];
648
 
      [s appendString: [[self objectAtIndex: i] description]];
 
1003
      unsigned  l = [separator length];
 
1004
      unsigned  i;
 
1005
 
 
1006
      [s appendString: [[self objectAtIndex: 0] description]];
 
1007
      for (i = 1; i < c; i++)
 
1008
        {
 
1009
          if (l > 0)
 
1010
            {
 
1011
              [s appendString: separator];
 
1012
            }
 
1013
          [s appendString: [[self objectAtIndex: i] description]];
 
1014
        }
649
1015
    }
650
 
  return s;
 
1016
  return AUTORELEASE([s makeImmutableCopyOnFail: NO]);
651
1017
}
652
1018
 
 
1019
/**
 
1020
 * Assumes that the receiver is an array of paths, and returns an
 
1021
 * array formed by selecting the subset of those patch matching
 
1022
 * the specified array of extensions.
 
1023
 */
653
1024
- (NSArray*) pathsMatchingExtensions: (NSArray*)extensions
654
1025
{
655
1026
  unsigned i, c = [self count];
656
 
  NSMutableArray *a = [NSMutableArray arrayWithCapacity: 1];
 
1027
  NSMutableArray *a = [[NSMutableArray alloc] initWithCapacity: 1];
657
1028
  Class cls = [NSString class];
658
1029
  IMP   get = [self methodForSelector: oaiSel];
659
1030
  IMP   add = [a methodForSelector: addSel];
663
1034
      id o = (*get)(self, oaiSel, i);
664
1035
 
665
1036
      if ([o isKindOfClass: cls])
666
 
        if ([extensions containsObject: [o pathExtension]])
667
 
          (*add)(a, addSel, o);
 
1037
        {
 
1038
          if ([extensions containsObject: [o pathExtension]])
 
1039
            {
 
1040
              (*add)(a, addSel, o);
 
1041
            }
 
1042
        }
668
1043
    }
669
 
  return a;
 
1044
  return AUTORELEASE([a makeImmutableCopyOnFail: NO]);
670
1045
}
671
1046
 
 
1047
/**
 
1048
 * Returns the first object found in the receiver (starting at index 0)
 
1049
 * which is present in the otherArray as determined by using the
 
1050
 * -containsObject: method.
 
1051
 */
672
1052
- (id) firstObjectCommonWithArray: (NSArray*)otherArray
673
1053
{
674
1054
  unsigned i, c = [self count];
675
1055
  id o;
 
1056
 
676
1057
  for (i = 0; i < c; i++)
677
 
    if ([otherArray containsObject: (o = [self objectAtIndex: i])])
678
 
      return o;
 
1058
    {
 
1059
      if ([otherArray containsObject: (o = [self objectAtIndex: i])])
 
1060
        {
 
1061
          return o;
 
1062
        }
 
1063
    }
679
1064
  return nil;
680
1065
}
681
1066
 
 
1067
/**
 
1068
 * Returns a subarray of the receiver containing the objects found in
 
1069
 * the specified range aRange.
 
1070
 */
682
1071
- (NSArray*) subarrayWithRange: (NSRange)aRange
683
1072
{
684
1073
  id na;
692
1081
    }
693
1082
  else
694
1083
    {
695
 
      id        objects[aRange.length];
 
1084
      GS_BEGINIDBUF(objects, aRange.length);
696
1085
 
697
1086
      [self getObjects: objects range: aRange];
698
1087
      na = [NSArray arrayWithObjects: objects count: aRange.length];
 
1088
      GS_ENDIDBUF();
699
1089
    }
700
1090
  return na;
701
1091
}
702
1092
 
 
1093
/**
 
1094
 * Returns an enumerator describing the array sequentially
 
1095
 * from the first to the last element.<br/>
 
1096
 * If you use a mutable subclass of NSArray,
 
1097
 * you should not modify the array during enumeration.
 
1098
 */
703
1099
- (NSEnumerator*) objectEnumerator
704
1100
{
705
1101
  id    e;
709
1105
  return AUTORELEASE(e);
710
1106
}
711
1107
 
 
1108
/**
 
1109
 * Returns an enumerator describing the array sequentially
 
1110
 * from the last to the first element.<br/>
 
1111
 * If you use a mutable subclass of NSArray,
 
1112
 * you should not modify the array during enumeration.
 
1113
 */
712
1114
- (NSEnumerator*) reverseObjectEnumerator
713
1115
{
714
1116
  id    e;
718
1120
  return AUTORELEASE(e);
719
1121
}
720
1122
 
 
1123
/**
 
1124
 * Returns the result of invoking -descriptionWithLocale:indent: with a nil
 
1125
 * locale and zero indent.
 
1126
 */
721
1127
- (NSString*) description
722
1128
{
723
1129
  return [self descriptionWithLocale: nil];
724
1130
}
725
1131
 
 
1132
/**
 
1133
 * Returns the result of invoking -descriptionWithLocale:indent:
 
1134
 * with a zero indent.
 
1135
 */
726
1136
- (NSString*) descriptionWithLocale: (NSDictionary*)locale
727
1137
{
728
1138
  return [self descriptionWithLocale: locale indent: 0];
729
1139
}
730
1140
 
 
1141
/**
 
1142
 * Returns the receiver as a text property list in the traditional format.<br />
 
1143
 * See [NSString-propertyList] for details.<br />
 
1144
 * If locale is nil, no formatting is done, otherwise entries are formatted
 
1145
 * according to the locale, and indented according to level.<br />
 
1146
 * Unless locale is nil, a level of zero indents items by four spaces,
 
1147
 * while a level of one indents them by a tab.<br />
 
1148
 * The items in the property list string appear in the same order as
 
1149
 * they appear in the receiver.
 
1150
 */
731
1151
- (NSString*) descriptionWithLocale: (NSDictionary*)locale
732
1152
                             indent: (unsigned int)level
733
1153
{
734
 
  NSMutableString       *result;
735
 
 
736
 
  result = [[NSMutableString alloc] initWithCapacity: 20*[self count]];
737
 
  result = AUTORELEASE(result);
738
 
  [self descriptionWithLocale: locale
739
 
                       indent: level
740
 
                           to: (id<GNUDescriptionDestination>)result];
741
 
  return result;
742
 
}
743
 
 
744
 
static NSString *indentStrings[] = {
745
 
  @"",
746
 
  @"    ",
747
 
  @"\t",
748
 
  @"\t    ",
749
 
  @"\t\t",
750
 
  @"\t\t    ",
751
 
  @"\t\t\t",
752
 
  @"\t\t\t    ",
753
 
  @"\t\t\t\t",
754
 
  @"\t\t\t\t    ",
755
 
  @"\t\t\t\t\t",
756
 
  @"\t\t\t\t\t    ",
757
 
  @"\t\t\t\t\t\t"
758
 
};
759
 
 
760
 
- (void) descriptionWithLocale: (NSDictionary*)locale
761
 
                        indent: (unsigned int)level
762
 
                            to: (id<GNUDescriptionDestination>)result
763
 
{
764
 
  unsigned              count = [self count];
765
 
  unsigned              last = count - 1;
766
 
  NSString              *plists[count];
767
 
  unsigned              i;
768
 
  IMP                   appImp;
769
 
 
770
 
  appImp = [(NSObject*)result methodForSelector: appSel];
771
 
 
772
 
  [self getObjects: plists];
773
 
 
774
 
  if (locale == nil)
775
 
    {
776
 
      (*appImp)(result, appSel, @"(");
777
 
      for (i = 0; i < count; i++)
778
 
        {
779
 
          id    item = plists[i];
780
 
 
781
 
          [item descriptionWithLocale: nil indent: 0 to: result];
782
 
          if (i != last)
783
 
            {
784
 
              (*appImp)(result, appSel, @", ");
785
 
            }
786
 
        }
787
 
      (*appImp)(result, appSel, @")");
788
 
    }
789
 
  else
790
 
    {
791
 
      NSString  *iBaseString;
792
 
      NSString  *iSizeString;
793
 
 
794
 
      if (level < sizeof(indentStrings)/sizeof(id))
795
 
        {
796
 
          iBaseString = indentStrings[level];
797
 
        }
798
 
      else
799
 
        {
800
 
          iBaseString = indentStrings[sizeof(indentStrings)/sizeof(id)-1];
801
 
        }
802
 
      level++;
803
 
      if (level < sizeof(indentStrings)/sizeof(id))
804
 
        {
805
 
          iSizeString = indentStrings[level];
806
 
        }
807
 
      else
808
 
        {
809
 
          iSizeString = indentStrings[sizeof(indentStrings)/sizeof(id)-1];
810
 
        }
811
 
 
812
 
      (*appImp)(result, appSel, @"(\n");
813
 
      for (i = 0; i < count; i++)
814
 
        {
815
 
          id    item = plists[i];
816
 
 
817
 
          (*appImp)(result, appSel, iSizeString);
818
 
     
819
 
          [item descriptionWithLocale: locale indent: level to: result];
820
 
          if (i == last)
821
 
            {
822
 
              (*appImp)(result, appSel, @"\n");
823
 
            }
824
 
          else
825
 
            {
826
 
              (*appImp)(result, appSel, @",\n");
827
 
            }
828
 
        }
829
 
      (*appImp)(result, appSel, iBaseString);
830
 
      (*appImp)(result, appSel, @")");
831
 
    }
832
 
}
833
 
 
834
 
- (BOOL) writeToFile: (NSString *)path atomically: (BOOL)useAuxilliaryFile
835
 
{
836
 
  extern BOOL   GSMacOSXCompatiblePropertyLists();
837
 
  NSDictionary  *loc;
838
 
  NSString      *desc;
839
 
 
840
 
  loc = GSUserDefaultsDictionaryRepresentation();
841
 
 
842
 
  if (GSMacOSXCompatiblePropertyLists() == YES)
843
 
    {
844
 
      extern NSString   *GSXMLPlMake(id obj, NSDictionary *loc);
845
 
 
846
 
      desc = GSXMLPlMake(self, loc);
847
 
    }
848
 
  else
849
 
    {
850
 
      NSMutableString   *result;
851
 
 
852
 
      result = [[NSMutableString alloc] initWithCapacity: 20*[self count]];
853
 
      result = AUTORELEASE(result);
854
 
      [self descriptionWithLocale: loc
855
 
                           indent: 0
856
 
                               to: (id<GNUDescriptionDestination>)result];
857
 
      desc = result;
858
 
    }
859
 
 
860
 
  return [desc writeToFile: path atomically: useAuxilliaryFile];
861
 
}
862
 
 
863
 
- (BOOL) writeToURL: (NSURL *)url atomically: (BOOL)useAuxilliaryFile
864
 
{
865
 
  extern BOOL   GSMacOSXCompatiblePropertyLists();
866
 
  NSDictionary  *loc;
867
 
  NSString      *desc;
868
 
 
869
 
  loc = GSUserDefaultsDictionaryRepresentation();
870
 
 
871
 
  if (GSMacOSXCompatiblePropertyLists() == YES)
872
 
    {
873
 
      extern NSString   *GSXMLPlMake(id obj, NSDictionary *loc);
874
 
 
875
 
      desc = GSXMLPlMake(self, loc);
876
 
    }
877
 
  else
878
 
    {
879
 
      NSMutableString   *result;
880
 
 
881
 
      result = [[NSMutableString alloc] initWithCapacity: 20*[self count]];
882
 
      result = AUTORELEASE(result);
883
 
      [self descriptionWithLocale: loc
884
 
                           indent: 0
885
 
                               to: (id<GNUDescriptionDestination>)result];
886
 
      desc = result;
887
 
    }
888
 
 
889
 
  return [desc writeToURL: url atomically: useAuxilliaryFile];
 
1154
  NSString      *result = nil;
 
1155
 
 
1156
  GSPropertyListMake(self, locale, NO, YES, level == 1 ? 3 : 2, &result);
 
1157
 
 
1158
  return result;
 
1159
}
 
1160
 
 
1161
/**
 
1162
 * <p>Writes the contents of the array to the file specified by path.
 
1163
 * The file contents will be in property-list format ... under GNUstep
 
1164
 * this is either OpenStep style (ASCII characters using \U hexadecimal
 
1165
 * escape sequences for unicode), or MacOS-X style (XML in the UTF8
 
1166
 * character set).
 
1167
 * </p>
 
1168
 * <p>If the useAuxiliaryFile flag is YES, the file write operation is
 
1169
 * atomic ... the data is written to a temporary file, which is then
 
1170
 * renamed to the actual file name.
 
1171
 * </p>
 
1172
 * <p>If the conversion of data into the correct property-list format fails
 
1173
 * or the write operation fails, the method returns NO, otherwise it
 
1174
 * returns YES.
 
1175
 * </p>
 
1176
 * <p>NB. The fact that the file is in property-list format does not
 
1177
 * necessarily mean that it can be used to reconstruct the array using
 
1178
 * the -initWithContentsOfFile: method.  If the original array contains
 
1179
 * non-property-list objects, the descriptions of those objects will
 
1180
 * have been written, and reading in the file as a property-list will
 
1181
 * result in a new array containing the string descriptions.
 
1182
 * </p>
 
1183
 */
 
1184
- (BOOL) writeToFile: (NSString *)path atomically: (BOOL)useAuxiliaryFile
 
1185
{
 
1186
  NSDictionary  *loc = GSUserDefaultsDictionaryRepresentation();
 
1187
  NSString      *desc = nil;
 
1188
  NSData        *data;
 
1189
 
 
1190
  if (GSMacOSXCompatiblePropertyLists() == YES)
 
1191
    {
 
1192
      GSPropertyListMake(self, loc, YES, NO, 2, &desc);
 
1193
      data = [desc dataUsingEncoding: NSUTF8StringEncoding];
 
1194
    }
 
1195
  else
 
1196
    {
 
1197
      GSPropertyListMake(self, loc, NO, NO, 2, &desc);
 
1198
      data = [desc dataUsingEncoding: NSASCIIStringEncoding];
 
1199
    }
 
1200
 
 
1201
  return [data writeToFile: path atomically: useAuxiliaryFile];
 
1202
}
 
1203
 
 
1204
/**
 
1205
 * <p>Writes the contents of the array to the specified url.
 
1206
 * This functions just like -writeToFile:atomically: except that the
 
1207
 * output may be written to any URL, not just a local file.
 
1208
 * </p>
 
1209
 */
 
1210
- (BOOL) writeToURL: (NSURL *)url atomically: (BOOL)useAuxiliaryFile
 
1211
{
 
1212
  NSDictionary  *loc = GSUserDefaultsDictionaryRepresentation();
 
1213
  NSString      *desc = nil;
 
1214
  NSData        *data;
 
1215
 
 
1216
  if (GSMacOSXCompatiblePropertyLists() == YES)
 
1217
    {
 
1218
      GSPropertyListMake(self, loc, YES, NO, 2, &desc);
 
1219
      data = [desc dataUsingEncoding: NSUTF8StringEncoding];
 
1220
    }
 
1221
  else
 
1222
    {
 
1223
      GSPropertyListMake(self, loc, NO, NO, 2, &desc);
 
1224
      data = [desc dataUsingEncoding: NSASCIIStringEncoding];
 
1225
    }
 
1226
 
 
1227
  return [data writeToURL: url atomically: useAuxiliaryFile];
 
1228
}
 
1229
 
 
1230
/**
 
1231
 * This overrides NSObjects implementation of this method.
 
1232
 * This method returns an array of objects returned by
 
1233
 * invoking -valueForKey: for each item in the receiver,
 
1234
 * substituting NSNull for nil.
 
1235
 * A special case: the key "count" is not forwarded to each object
 
1236
 * of the receiver but returns the number of objects of the receiver.<br/>
 
1237
 */
 
1238
- (id) valueForKey: (NSString*)key
 
1239
{
 
1240
  id result = nil;
 
1241
 
 
1242
  if ([key isEqualToString: @"count"] == YES)
 
1243
    {
 
1244
      result = [NSNumber numberWithUnsignedInt: [self count]];
 
1245
    }
 
1246
  else
 
1247
    {
 
1248
      NSMutableArray    *results = nil;
 
1249
      static NSNull     *null = nil;
 
1250
      unsigned          i;
 
1251
      unsigned          count = [self count];
 
1252
      volatile id       object = nil;
 
1253
 
 
1254
      results = [NSMutableArray array];
 
1255
 
 
1256
      for (i = 0; i < count; i++)
 
1257
        {
 
1258
          id    result;
 
1259
 
 
1260
          object = [self objectAtIndex: i];
 
1261
          result = [object valueForKey: key];
 
1262
          if (result == nil)
 
1263
            {
 
1264
              if (null == nil)
 
1265
                {
 
1266
                  null = RETAIN([NSNull null]);
 
1267
                }
 
1268
              result = null;
 
1269
            }
 
1270
 
 
1271
          [results addObject: result];
 
1272
        }
 
1273
 
 
1274
      result = results;
 
1275
    }
 
1276
  return result;
890
1277
}
891
1278
 
892
1279
@end
893
1280
 
894
1281
 
 
1282
/**
 
1283
 *  <code>NSMutableArray</code> is the mutable version of [NSArray].  It
 
1284
 *  provides methods for altering the contents of the array.
 
1285
 */
895
1286
@implementation NSMutableArray
896
1287
 
897
1288
+ (void) initialize
926
1317
  return NSMutableArrayClass;
927
1318
}
928
1319
 
929
 
/* The NSCopying Protocol */
930
 
 
931
 
- (id) copyWithZone: (NSZone*)zone
932
 
{
933
 
  /* a deep copy */
934
 
  unsigned      count = [self count];
935
 
  id            objects[count];
936
 
  NSArray       *newArray;
937
 
  unsigned      i;
938
 
 
939
 
  [self getObjects: objects];
940
 
  for (i = 0; i < count; i++)
941
 
    objects[i] = [objects[i] copyWithZone: zone];
942
 
  newArray = [[GSArrayClass allocWithZone: zone]
943
 
    initWithObjects: objects count: count];
944
 
  while (i > 0)
945
 
    RELEASE(objects[--i]);
946
 
  return newArray;
947
 
}
948
 
 
949
 
/* This is the desgnated initializer for NSMutableArray */
 
1320
/** <init /> <override-subclass />
 
1321
 * Initialise the array with the specified capacity ... this
 
1322
 * should ensure that the array can have numItems added efficiently.<br />
 
1323
 * Calls -init (which does nothing but maintain MacOS-X compatibility),
 
1324
 * and needs to be re-implemented in subclasses in order to have all
 
1325
 * other initialisers work.
 
1326
 */
950
1327
- (id) initWithCapacity: (unsigned)numItems
951
1328
{
952
 
  [self subclassResponsibility: _cmd];
953
 
  return nil;
954
 
}
955
 
 
956
 
- (void) addObject: anObject
957
 
{
958
 
  [self subclassResponsibility: _cmd];
959
 
}
960
 
 
961
 
- (void) replaceObjectAtIndex: (unsigned)index withObject: anObject
962
 
{
963
 
  [self subclassResponsibility: _cmd];
964
 
}
965
 
 
 
1329
  self = [self init];
 
1330
  return self;
 
1331
}
 
1332
 
 
1333
/** <override-subclass />
 
1334
 * Adds anObject at the end of the array, thus increasing the size of
 
1335
 * the array.  The object is retained upon addition.
 
1336
 */
 
1337
- (void) addObject: (id)anObject
 
1338
{
 
1339
  [self subclassResponsibility: _cmd];
 
1340
}
 
1341
 
 
1342
/**
 
1343
 * Swaps the positions of two objects in the array.  Raises an exception
 
1344
 * if either array index is out of bounds.
 
1345
 */
 
1346
- (void) exchangeObjectAtIndex: (unsigned int)i1
 
1347
             withObjectAtIndex: (unsigned int)i2
 
1348
{
 
1349
  id    tmp = [self objectAtIndex: i1];
 
1350
 
 
1351
  RETAIN(tmp);
 
1352
  [self replaceObjectAtIndex: i1 withObject: [self objectAtIndex: i2]];
 
1353
  [self replaceObjectAtIndex: i2 withObject: tmp];
 
1354
  RELEASE(tmp);
 
1355
}
 
1356
 
 
1357
/** <override-subclass />
 
1358
 * Places an object into the receiver at the specified location.<br />
 
1359
 * Raises an exception if given an array index which is too large.<br />
 
1360
 * The object is retained by the array.
 
1361
 */
 
1362
- (void) replaceObjectAtIndex: (unsigned)index withObject: (id)anObject
 
1363
{
 
1364
  [self subclassResponsibility: _cmd];
 
1365
}
 
1366
 
 
1367
/**
 
1368
 * Replaces objects in the receiver with those from anArray.<br />
 
1369
 * Raises an exception if given a range extending beyond the array.<br />
 
1370
 */
966
1371
- (void) replaceObjectsInRange: (NSRange)aRange
967
1372
          withObjectsFromArray: (NSArray*)anArray
968
1373
{
977
1382
    [self insertObject: o atIndex: aRange.location];
978
1383
}
979
1384
 
 
1385
/**
 
1386
 * Replaces objects in the receiver with some of those from anArray.<br />
 
1387
 * Raises an exception if given a range extending beyond the array.<br />
 
1388
 */
980
1389
- (void) replaceObjectsInRange: (NSRange)aRange
981
1390
          withObjectsFromArray: (NSArray*)anArray
982
1391
                         range: (NSRange)anotherRange
985
1394
         withObjectsFromArray: [anArray subarrayWithRange: anotherRange]];
986
1395
}
987
1396
 
 
1397
/** <override-subclass />
 
1398
 * Inserts an object into the receiver at the specified location.<br />
 
1399
 * Raises an exception if given an array index which is too large.<br />
 
1400
 * The size of the array increases by one.<br />
 
1401
 * The object is retained by the array.
 
1402
 */
988
1403
- (void) insertObject: anObject atIndex: (unsigned)index
989
1404
{
990
1405
  [self subclassResponsibility: _cmd];
991
1406
}
992
1407
 
 
1408
/** <override-subclass />
 
1409
 * Removes an object from the receiver at the specified location.<br />
 
1410
 * The size of the array decreases by one.<br />
 
1411
 * Raises an exception if given an array index which is too large.<br />
 
1412
 */
993
1413
- (void) removeObjectAtIndex: (unsigned)index
994
1414
{
995
1415
  [self subclassResponsibility: _cmd];
996
1416
}
997
1417
 
 
1418
/**
 
1419
 * Creates an autoreleased mutable array anble to store at least numItems.
 
1420
 * See the -initWithCapacity: method.
 
1421
 */
998
1422
+ (id) arrayWithCapacity: (unsigned)numItems
999
1423
{
1000
1424
  return AUTORELEASE([[self allocWithZone: NSDefaultMallocZone()]
1001
1425
    initWithCapacity: numItems]);
1002
1426
}
1003
1427
 
1004
 
/* Override our superclass's designated initializer to go our's */
 
1428
/**
 
1429
 * Override our superclass's designated initializer to go our's
 
1430
 */
1005
1431
- (id) initWithObjects: (id*)objects count: (unsigned)count
1006
1432
{
1007
1433
  self = [self initWithCapacity: count];
1016
1442
  return self;
1017
1443
}
1018
1444
 
 
1445
/**
 
1446
 * Removes the last object in the array.  Raises an exception if the array
 
1447
 * is already empty.
 
1448
 */
1019
1449
- (void) removeLastObject
1020
1450
{
1021
1451
  unsigned      count = [self count];
1026
1456
  [self removeObjectAtIndex: count-1];
1027
1457
}
1028
1458
 
 
1459
/**
 
1460
 * Removes all occurrences of anObject (found by pointer equality)
 
1461
 * from the receiver.
 
1462
 */
1029
1463
- (void) removeObjectIdenticalTo: (id)anObject
1030
1464
{
1031
1465
  unsigned      i;
1057
1491
    }
1058
1492
}
1059
1493
 
 
1494
/**
 
1495
 * Removes all occurrences of anObject (found by the -isEqual: method
 
1496
 * of anObject) aRange in the receiver.
 
1497
 */
1060
1498
- (void) removeObject: (id)anObject inRange: (NSRange)aRange
1061
1499
{
1062
1500
  unsigned      c;
1101
1539
              (*rem)(self, remSel, i);
1102
1540
            }
1103
1541
        }
1104
 
#ifndef GS_WITH_GC
 
1542
#if GS_WITH_GC == 0
1105
1543
      if (rem != 0)
1106
1544
        {
1107
1545
          RELEASE(anObject);
1110
1548
    }
1111
1549
}
1112
1550
 
 
1551
/**
 
1552
 * Removes all occurrances of anObject (found by pointer equality)
 
1553
 * from aRange in the receiver.
 
1554
 */
1113
1555
- (void) removeObjectIdenticalTo: (id)anObject inRange: (NSRange)aRange
1114
1556
{
1115
1557
  unsigned      c;
1149
1591
    }
1150
1592
}
1151
1593
 
 
1594
/**
 
1595
 * Removes all occurrences of anObject (found by anObjects -isEqual: method)
 
1596
 * from the receiver.
 
1597
 */
1152
1598
- (void) removeObject: (id)anObject
1153
1599
{
1154
1600
  unsigned      i;
1194
1640
    }
1195
1641
}
1196
1642
 
 
1643
/**
 
1644
 * Removes all objects from the receiver, leaving an empty array.
 
1645
 */
1197
1646
- (void) removeAllObjects
1198
1647
{
1199
1648
  unsigned      c = [self count];
1209
1658
    }
1210
1659
}
1211
1660
 
 
1661
/**
 
1662
 * Adds each object from otherArray to the receiver, in first to last order.
 
1663
 */
1212
1664
- (void) addObjectsFromArray: (NSArray*)otherArray
1213
1665
{
1214
1666
  unsigned c = [otherArray count];
1224
1676
    }
1225
1677
}
1226
1678
 
 
1679
/**
 
1680
 * Sets the contents of the receiver to be identical to the contents
 
1681
 * of othrArray.
 
1682
 */
1227
1683
- (void) setArray: (NSArray *)otherArray
1228
1684
{
1229
1685
  [self removeAllObjects];
1230
1686
  [self addObjectsFromArray: otherArray];
1231
1687
}
1232
1688
 
1233
 
- (void) removeObjectsFromIndices: (unsigned*)indices 
 
1689
/**
 
1690
 * Supplied with a C array of indices containing count values, this method
 
1691
 * removes all corresponding objects from the receiver.  The objects are
 
1692
 * removed in such a way that the removal is <em>safe</em> irrespective
 
1693
 * of the order in which they are specified in the indices array.
 
1694
 */
 
1695
- (void) removeObjectsFromIndices: (unsigned*)indices
1234
1696
                       numIndices: (unsigned)count
1235
1697
{
1236
1698
  if (count > 0)
1237
1699
    {
1238
 
      unsigned  sorted[count];
1239
1700
      unsigned  to = 0;
1240
1701
      unsigned  from = 0;
1241
1702
      unsigned  i;
 
1703
      GS_BEGINITEMBUF(sorted, count, unsigned int);
1242
1704
 
1243
1705
      while (from < count)
1244
1706
        {
1245
1707
          unsigned      val = indices[from++];
1246
1708
 
1247
1709
          i = to;
1248
 
          while (i > 0 && sorted[i] > val)
 
1710
          while (i > 0 && sorted[i-1] > val)
1249
1711
            {
1250
1712
              i--;
1251
1713
            }
1279
1741
              (*rem)(self, remSel, sorted[to]);
1280
1742
            }
1281
1743
        }
 
1744
      GS_ENDITEMBUF();
1282
1745
    }
1283
1746
}
1284
1747
 
 
1748
/**
 
1749
 * Removes from the receiver, all the objects present in otherArray,
 
1750
 * as determined by using the -isEqual: method.
 
1751
 */
1285
1752
- (void) removeObjectsInArray: (NSArray*)otherArray
1286
1753
{
1287
1754
  unsigned      c = [otherArray count];
1297
1764
    }
1298
1765
}
1299
1766
 
 
1767
/**
 
1768
 * Removes all the objects in aRange from the receiver.
 
1769
 */
1300
1770
- (void) removeObjectsInRange: (NSRange)aRange
1301
1771
{
1302
1772
  unsigned      i;
1319
1789
    }
1320
1790
}
1321
1791
 
 
1792
/**
 
1793
 * Sorts the array according to the supplied comparator.
 
1794
 */
1322
1795
- (void) sortUsingSelector: (SEL)comparator
1323
1796
{
1324
1797
  [self sortUsingFunction: compare context: (void *)comparator];
1325
1798
}
1326
1799
 
1327
 
- (void) sortUsingFunction: (int(*)(id,id,void*))compare 
 
1800
/**
 
1801
 * Sorts the array according to the supplied compare function
 
1802
 * with the context information.
 
1803
 */
 
1804
- (void) sortUsingFunction: (NSComparisonResult (*)(id,id,void*))compare
1328
1805
                   context: (void*)context
1329
1806
{
1330
1807
  /* Shell sort algorithm taken from SortingInAction - a NeXT example */
1331
1808
#define STRIDE_FACTOR 3 // good value for stride factor is not well-understood
1332
1809
                        // 3 is a fairly good choice (Sedgewick)
1333
 
  unsigned      c,d, stride;
 
1810
  unsigned int  c;
 
1811
  unsigned int  d;
 
1812
  unsigned int  stride = 1;
1334
1813
  BOOL          found;
1335
 
  int           count = [self count];
 
1814
  unsigned int  count = [self count];
1336
1815
#ifdef  GSWARN
1337
1816
  BOOL          badComparison = NO;
1338
1817
#endif
1339
1818
 
1340
 
  stride = 1;
1341
1819
  while (stride <= count)
1342
1820
    {
1343
1821
      stride = stride * STRIDE_FACTOR + 1;
1344
1822
    }
1345
 
    
1346
 
  while(stride > (STRIDE_FACTOR - 1))
 
1823
 
 
1824
  while (stride > (STRIDE_FACTOR - 1))
1347
1825
    {
1348
1826
      // loop to sort for each value of stride
1349
1827
      stride = stride / STRIDE_FACTOR;
1401
1879
#endif
1402
1880
}
1403
1881
 
 
1882
/**
 
1883
 * Call setValue:forKey: on each of the receiver's items
 
1884
 * with the value and key.
 
1885
 */
 
1886
- (void) setValue: (id)value forKey: (NSString*)key
 
1887
{
 
1888
  unsigned      i;
 
1889
  unsigned      count = [self count];
 
1890
  volatile id   object = nil;
 
1891
 
 
1892
  for (i = 0; i < count; i++)
 
1893
    {
 
1894
      object = [self objectAtIndex: i];
 
1895
      [object setValue: value
 
1896
                forKey: key];
 
1897
    }
 
1898
}
1404
1899
@end
1405
1900
 
1406
1901
@interface NSArrayEnumerator : NSEnumerator
1417
1912
 
1418
1913
- (id) initWithArray: (NSArray*)anArray
1419
1914
{
1420
 
  [super init];
1421
 
  array = anArray;
1422
 
  IF_NO_GC(RETAIN(array));
1423
 
  pos = 0;
1424
 
  get = [array methodForSelector: oaiSel];
1425
 
  cnt = (unsigned (*)(NSArray*, SEL))[array methodForSelector: countSel];
 
1915
  self = [super init];
 
1916
  if (self != nil)
 
1917
    {
 
1918
      array = anArray;
 
1919
      IF_NO_GC(RETAIN(array));
 
1920
      pos = 0;
 
1921
      get = [array methodForSelector: oaiSel];
 
1922
      cnt = (unsigned (*)(NSArray*, SEL))[array methodForSelector: countSel];
 
1923
    }
1426
1924
  return self;
1427
1925
}
1428
1926
 
 
1927
/**
 
1928
 * Returns the next object in the enumeration or nil if there are no more
 
1929
 * objects.<br />
 
1930
 * NB. modifying a mutable array during an enumeration can break things ...
 
1931
 * don't do it.
 
1932
 */
1429
1933
- (id) nextObject
1430
1934
{
1431
1935
  if (pos >= (*cnt)(array, countSel))
1448
1952
 
1449
1953
- (id) initWithArray: (NSArray*)anArray
1450
1954
{
1451
 
  [super initWithArray: anArray];
1452
 
  pos = (*cnt)(array, countSel);
 
1955
  self = [super initWithArray: anArray];
 
1956
  if (self != nil)
 
1957
    {
 
1958
      pos = (*cnt)(array, countSel);
 
1959
    }
1453
1960
  return self;
1454
1961
}
1455
1962
 
 
1963
/**
 
1964
 * Returns the next object in the enumeration or nil if there are no more
 
1965
 * objects.<br />
 
1966
 * NB. modifying a mutable array during an enumeration can break things ...
 
1967
 * don't do it.
 
1968
 */
1456
1969
- (id) nextObject
1457
1970
{
1458
1971
  if (pos == 0)
1461
1974
}
1462
1975
@end
1463
1976
 
1464
 
 
 
1977
/**
 
1978
 *  [NSArray] enhancements provided by GNUstep.
 
1979
 */
1465
1980
@implementation NSArray (GNUstep)
1466
1981
 
1467
 
/*
1468
 
 *      The comparator function takes two items as arguments, the first is the
1469
 
 *      item to be added, the second is the item already in the array.
1470
 
 *      The function should return NSOrderedAscending if the item to be
1471
 
 *      added is 'less than' the item in the array, NSOrderedDescending
1472
 
 *      if it is greater, and NSOrderedSame if it is equal.
 
1982
/**
 
1983
 * Locate the correct insertion position for item where the receiver is
 
1984
 * a sorted array witch was sorted using the sorter function.<br />
 
1985
 * The comparator function takes two items as arguments, the first is the
 
1986
 * item to be added, the second is the item already in the array.
 
1987
 * The function should return NSOrderedAscending if the item to be
 
1988
 * added is 'less than' the item in the array, NSOrderedDescending
 
1989
 * if it is greater, and NSOrderedSame if it is equal.
1473
1990
 */
1474
1991
- (unsigned) insertionPosition: (id)item
1475
1992
                 usingFunction: (NSComparisonResult (*)(id, id, void *))sorter
1518
2035
   *    Now skip past any equal items so the insertion point is AFTER any
1519
2036
   *    items that are equal to the new one.
1520
2037
   */
1521
 
  while (index < count
1522
 
    && (*sorter)(item, (*oai)(self, oaiSel, index), context) != NSOrderedAscending)
 
2038
  while (index < count && (*sorter)(item, (*oai)(self, oaiSel, index), context)
 
2039
    != NSOrderedAscending)
1523
2040
    {
1524
2041
      index++;
1525
2042
    }
1526
2043
  return index;
1527
2044
}
1528
2045
 
 
2046
/**
 
2047
 * Locate the correct insertion position for item where the receiver is
 
2048
 * a sorted array which was sorted using the comp selector.
 
2049
 */
1529
2050
- (unsigned) insertionPosition: (id)item
1530
2051
                 usingSelector: (SEL)comp
1531
2052
{