PageRenderTime 117ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/src/NSArray.m

https://github.com/jsyedidia/nufound
Objective C | 1190 lines | 890 code | 204 blank | 96 comment | 141 complexity | ef6a61ad0f9749b083f8dc56e6b0b050 MD5 | raw file
Possible License(s): Apache-2.0
  1. /*
  2. NSArray.m
  3. Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
  4. All rights reserved.
  5. Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
  6. This file is part of libFoundation.
  7. Permission to use, copy, modify, and distribute this software and its
  8. documentation for any purpose and without fee is hereby granted, provided
  9. that the above copyright notice appear in all copies and that both that
  10. copyright notice and this permission notice appear in supporting
  11. documentation.
  12. We disclaim all warranties with regard to this software, including all
  13. implied warranties of merchantability and fitness, in no event shall
  14. we be liable for any special, indirect or consequential damages or any
  15. damages whatsoever resulting from loss of use, data or profits, whether in
  16. an action of contract, negligence or other tortious action, arising out of
  17. or in connection with the use or performance of this software.
  18. */
  19. #include <stdarg.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <Foundation/common.h>
  23. #include <Foundation/NSObject.h>
  24. #include <Foundation/NSArray.h>
  25. #include <Foundation/NSRange.h>
  26. #include <Foundation/NSString.h>
  27. #include <Foundation/NSAutoreleasePool.h>
  28. #include <Foundation/NSException.h>
  29. #include <Foundation/NSCoder.h>
  30. #include <Foundation/PropertyListParser.h>
  31. #include <Foundation/NSUtilities.h>
  32. #include <Foundation/NSURL.h>
  33. #include <Foundation/exceptions/GeneralExceptions.h>
  34. #include "NSConcreteArray.h"
  35. #include "NSObject+PropLists.h"
  36. /*
  37. * NSArray Implementation
  38. *
  39. * primary methods are
  40. * init
  41. * initWithObjects:count:
  42. * dealloc
  43. * count
  44. * objectAtIndex:
  45. */
  46. @implementation NSArray
  47. static Class NSArrayClass = Nil;
  48. static Class NSMutableArrayClass = Nil;
  49. static Class NSConcreteArrayClass = Nil;
  50. /* Allocating and Initializing an Array */
  51. + (id)allocWithZone:(NSZone*)zone
  52. {
  53. if (NSArrayClass == Nil)
  54. NSArrayClass = [NSArray class];
  55. if (NSConcreteArrayClass == Nil)
  56. NSConcreteArrayClass = [NSConcreteArray class];
  57. return NSAllocateObject( (self == NSArrayClass) ?
  58. NSConcreteArrayClass : (Class)self, 0, zone);
  59. }
  60. + (id)array
  61. {
  62. return AUTORELEASE([[self alloc] init]);
  63. }
  64. + (id)arrayWithObject:(id)anObject
  65. {
  66. return AUTORELEASE([[self alloc] initWithObjects:&anObject count:1]);
  67. }
  68. + (id)arrayWithObjects:(id)firstObj,...
  69. {
  70. id array, obj, *objects;
  71. va_list list;
  72. unsigned int count;
  73. va_start(list, firstObj);
  74. for (count=0, obj = firstObj; obj; obj = va_arg(list,id))
  75. count++;
  76. va_end(list);
  77. objects = Malloc(sizeof(id) * count);
  78. {
  79. va_start(list, firstObj);
  80. for (count = 0, obj = firstObj; obj; obj = va_arg(list,id))
  81. objects[count++] = obj;
  82. va_end(list);
  83. array = [[self alloc] initWithObjects:objects count:count];
  84. }
  85. lfFree(objects);
  86. return AUTORELEASE(array);
  87. }
  88. + (id)arrayWithArray:(NSArray*)anotherArray
  89. {
  90. return AUTORELEASE([[self alloc] initWithArray:anotherArray]);
  91. }
  92. + (id)arrayWithContentsOfFile:(NSString *)fileName
  93. {
  94. volatile id plist = nil;
  95. NSString *format = @"%@: Caught exception %@ with reason %@ ";
  96. NS_DURING {
  97. plist = NSParsePropertyListFromFile(fileName);
  98. if (NSArrayClass == Nil)
  99. NSArrayClass = [NSArray class];
  100. if (![plist isKindOfClass:NSArrayClass])
  101. plist = nil;
  102. }
  103. NS_HANDLER {
  104. NSLog(format, self, [localException name], [localException reason]);
  105. plist = nil;
  106. }
  107. NS_ENDHANDLER;
  108. return plist;
  109. }
  110. + (id)arrayWithContentsOfURL:(NSURL *)_url
  111. {
  112. id plist;
  113. if ([_url isFileURL])
  114. return [self arrayWithContentsOfFile:[_url path]];
  115. if (NSArrayClass == Nil)
  116. NSArrayClass = [NSArray class];
  117. plist = [[NSString stringWithContentsOfURL:_url] propertyList];
  118. if (![plist isKindOfClass:NSArrayClass])
  119. return nil;
  120. return plist;
  121. }
  122. + (id)arrayWithObjects:(id*)objects count:(unsigned int)count
  123. {
  124. return AUTORELEASE([[self alloc]
  125. initWithObjects:objects count:count]);
  126. }
  127. - (NSArray*)arrayByAddingObject:(id)anObject
  128. {
  129. int i, count = [self count];
  130. id array;
  131. id *objects;
  132. objects = Malloc(sizeof(id) * (count + 1));
  133. {
  134. for (i = 0; i < count; i++)
  135. objects[i] = [self objectAtIndex:i];
  136. objects[i] = anObject;
  137. if (NSArrayClass == Nil)
  138. NSArrayClass = [NSArray class];
  139. array = AUTORELEASE([[NSArrayClass alloc]
  140. initWithObjects:objects count:count+1]);
  141. }
  142. lfFree(objects);
  143. return array;
  144. }
  145. - (NSArray*)arrayByAddingObjectsFromArray:(NSArray*)anotherArray;
  146. {
  147. unsigned int i, count = [self count], another = [anotherArray count];
  148. id array;
  149. id *objects;
  150. objects = Malloc(sizeof(id) * (count+another));
  151. {
  152. for (i = 0; i < count; i++)
  153. objects[i] = [self objectAtIndex:i];
  154. for (i = 0; i < another; i++)
  155. objects[i + count] = [anotherArray objectAtIndex:i];
  156. if (NSArrayClass == Nil)
  157. NSArrayClass = [NSArray class];
  158. array = AUTORELEASE([[NSArrayClass alloc]
  159. initWithObjects:objects count:count + another]);
  160. }
  161. lfFree(objects);
  162. return array;
  163. }
  164. - (id)initWithArray:(NSArray*)anotherArray
  165. {
  166. return [self initWithArray:anotherArray copyItems:NO];
  167. }
  168. - (id)initWithArray:(NSArray*)anotherArray copyItems:(BOOL)flag;
  169. {
  170. unsigned int i, count = [anotherArray count];
  171. id *objects;
  172. if (count == 0)
  173. return [self initWithObjects:NULL count:0];
  174. objects = Malloc(sizeof(id) * count);
  175. {
  176. for (i = 0; i < count; i++) {
  177. objects[i] = flag
  178. ? [anotherArray objectAtIndex:i]
  179. : AUTORELEASE([[anotherArray objectAtIndex:i] copyWithZone:NULL]);
  180. }
  181. self = [self initWithObjects:objects count:count];
  182. }
  183. lfFree(objects);
  184. return self;
  185. }
  186. - (id)initWithObjects:(id)firstObj,...
  187. {
  188. id obj, *objects;
  189. va_list list;
  190. unsigned int count;
  191. va_start(list, firstObj);
  192. for (count = 0, obj = firstObj; obj; obj = va_arg(list,id))
  193. count++;
  194. va_end(list);
  195. objects = Malloc(sizeof(id) * count);
  196. {
  197. va_start(list, firstObj);
  198. for (count = 0, obj = firstObj; obj; obj = va_arg(list,id))
  199. objects[count++] = obj;
  200. va_end(list);
  201. self = [self initWithObjects:objects count:count];
  202. }
  203. lfFree(objects);
  204. return self;
  205. }
  206. - (id)initWithObjects:(id*)objects count:(unsigned int)count
  207. {
  208. [self subclassResponsibility:_cmd];
  209. return self;
  210. }
  211. - (id)initWithContentsOfFile:(NSString*)fileName
  212. {
  213. NSArray *plist;
  214. if (NSArrayClass == Nil)
  215. NSArrayClass = [NSArray class];
  216. if ((plist = [NSArrayClass arrayWithContentsOfFile:fileName])) {
  217. return [self initWithArray:plist];
  218. }
  219. else {
  220. self = AUTORELEASE(self);
  221. return nil;
  222. }
  223. }
  224. - (id)initWithContentsOfURL:(NSURL *)_url
  225. {
  226. NSArray *plist;
  227. if (NSArrayClass == Nil)
  228. NSArrayClass = [NSArray class];
  229. if ((plist = [NSArrayClass arrayWithContentsOfURL:_url])) {
  230. return [self initWithArray:plist];
  231. }
  232. else {
  233. self = AUTORELEASE(self);
  234. return nil;
  235. }
  236. }
  237. /* Querying the Array */
  238. - (BOOL)containsObject:(id)anObject
  239. {
  240. return ([self indexOfObject:anObject] == NSNotFound) ? NO : YES;
  241. }
  242. - (unsigned int)count
  243. {
  244. [self subclassResponsibility:_cmd];
  245. return 0;
  246. }
  247. - (unsigned int)indexOfObject:(id)anObject
  248. {
  249. return [self indexOfObject:anObject
  250. inRange:NSMakeRange(0, [self count])];
  251. }
  252. - (unsigned int)indexOfObjectIdenticalTo:(id)anObject;
  253. {
  254. return [self indexOfObjectIdenticalTo:anObject
  255. inRange:NSMakeRange(0, [self count])];
  256. }
  257. - (unsigned int)indexOfObject:(id)anObject inRange:(NSRange)aRange
  258. {
  259. unsigned int index;
  260. for (index = 0; index < aRange.length; index++)
  261. if ([anObject isEqual:[self objectAtIndex:aRange.location+index]])
  262. return aRange.location+index;
  263. return NSNotFound;
  264. }
  265. - (unsigned int)indexOfObjectIdenticalTo:(id)anObject inRange:(NSRange)aRange
  266. {
  267. unsigned int index;
  268. for (index = 0; index < aRange.length; index++)
  269. if (anObject == [self objectAtIndex:aRange.location+index])
  270. return index;
  271. return NSNotFound;
  272. }
  273. - (id)lastObject
  274. {
  275. int count = [self count];
  276. return count ? [self objectAtIndex:count - 1] : nil;
  277. }
  278. - (id)objectAtIndex:(unsigned int)index
  279. {
  280. [self subclassResponsibility:_cmd];
  281. return self;
  282. }
  283. - (void)getObjects:(id *)buffer
  284. {
  285. unsigned i, count = [self count];
  286. for (i = 0; i < count; i++) {
  287. buffer[i] = [self objectAtIndex: i];
  288. }
  289. }
  290. - (void)getObjects:(id *)buffer range:(NSRange)range
  291. {
  292. /* naive implementation, to be fixed ... */
  293. return [[self subarrayWithRange:range] getObjects:buffer];
  294. }
  295. - (NSEnumerator *)objectEnumerator
  296. {
  297. return AUTORELEASE([[_NSArrayEnumerator alloc]
  298. initWithArray:self reverse:NO]);
  299. }
  300. - (NSEnumerator *)reverseObjectEnumerator
  301. {
  302. return AUTORELEASE([[_NSArrayEnumerator alloc]
  303. initWithArray:self reverse:YES]);
  304. }
  305. /* Sending Messages to Elements */
  306. - (void)makeObjectsPerformSelector:(SEL)aSelector
  307. {
  308. unsigned int index, count = [self count];
  309. for (index = 0; index < count; index++)
  310. [[self objectAtIndex:index] performSelector:aSelector];
  311. }
  312. - (void)makeObjectsPerformSelector:(SEL)aSelector withObject:(id)anObject
  313. {
  314. unsigned int index, count = [self count];
  315. for (index = 0; index < count; index++)
  316. [[self objectAtIndex:index]
  317. performSelector:aSelector withObject:anObject];
  318. }
  319. /* Obsolete methods */
  320. - (void)makeObjectsPerform:(SEL)aSelector
  321. {
  322. unsigned int index, count = [self count];
  323. for (index = 0; index < count; index++)
  324. [[self objectAtIndex:index] performSelector:aSelector];
  325. }
  326. - (void)makeObjectsPerform:(SEL)aSelector withObject:(id)anObject
  327. {
  328. unsigned int index, count = [self count];
  329. for (index = 0; index < count; index++)
  330. [[self objectAtIndex:index]
  331. performSelector:aSelector withObject:anObject];
  332. }
  333. /* Comparing Arrays */
  334. - (id)firstObjectCommonWithArray:(NSArray*)otherArray
  335. {
  336. unsigned int index, count = [self count];
  337. for (index = 0; index < count; index++) {
  338. id object = [self objectAtIndex:index];
  339. if ([otherArray containsObject:object])
  340. return object;
  341. }
  342. return nil;
  343. }
  344. - (BOOL)isEqualToArray:(NSArray*)otherArray
  345. {
  346. unsigned int index, count;
  347. if( otherArray == self )
  348. return YES;
  349. if ([otherArray count] != (count = [self count]))
  350. return NO;
  351. for (index = 0; index < count; index++) {
  352. register id o1, o2;
  353. o1 = [self objectAtIndex:index];
  354. o2 = [otherArray objectAtIndex:index];
  355. if (![o1 isEqual:o2])
  356. return NO;
  357. }
  358. return YES;
  359. }
  360. /* Deriving New Arrays */
  361. - (NSArray *)sortedArrayUsingFunction:
  362. (int(*)(id element1, id element2, void *userData))comparator
  363. context:(void *)context
  364. {
  365. NSMutableArray *sortedArray;
  366. NSArray *result;
  367. sortedArray = [self mutableCopy];
  368. [sortedArray sortUsingFunction:comparator context:context];
  369. result = [sortedArray copy];
  370. RELEASE(sortedArray);
  371. return AUTORELEASE(result);
  372. }
  373. static int compare(id elem1, id elem2, void* comparator)
  374. {
  375. return (int)(long)[elem1 performSelector:comparator withObject:elem2];
  376. }
  377. - (NSArray*)sortedArrayUsingSelector:(SEL)comparator
  378. // Returns an array listing the receiver's elements in ascending order,
  379. // as determined by the comparison method specified by the selector
  380. // comparator.
  381. {
  382. return [self sortedArrayUsingFunction:compare context:(void*)comparator];
  383. }
  384. - (NSArray*)subarrayWithRange:(NSRange)range
  385. {
  386. id array;
  387. unsigned int index;
  388. id *objects;
  389. objects = Malloc(sizeof(id) * range.length);
  390. {
  391. for (index = 0; index < range.length; index++)
  392. objects[index] = [self objectAtIndex:range.location+index];
  393. if (NSArrayClass == Nil)
  394. NSArrayClass = [NSArray class];
  395. array = AUTORELEASE([[NSArrayClass alloc]
  396. initWithObjects:objects count:range.length]);
  397. }
  398. lfFree(objects);
  399. return array;
  400. }
  401. // Returns an array containing the receiver's elements
  402. // that fall within the limits specified by range.
  403. /* Joining String Elements */
  404. - (NSString*)componentsJoinedByString:(NSString*)separator
  405. {
  406. unsigned int index, count = [self count];
  407. if (!separator)
  408. separator = @"";
  409. if (count > 0) {
  410. NSMutableString* string = [NSMutableString new];
  411. id elem;
  412. SEL sel;
  413. IMP imp;
  414. CREATE_AUTORELEASE_POOL(pool);
  415. elem = [self objectAtIndex:0];
  416. sel = @selector(appendString:);
  417. imp = [string methodForSelector:sel];
  418. if (![elem isKindOfClass:[NSString class]])
  419. elem = [elem description];
  420. (*imp)(string, sel, elem);
  421. for (index = 1; index < count; index++) {
  422. elem = [self objectAtIndex:index];
  423. if (![elem isKindOfClass:[NSString class]])
  424. elem = [elem description];
  425. (*imp)(string, sel, separator);
  426. (*imp)(string, sel, elem);
  427. }
  428. RELEASE(pool);
  429. return AUTORELEASE(string);
  430. }
  431. return @"";
  432. }
  433. /* Creating a String Description of the Array */
  434. - (NSString *)propertyListStringWithLocale:(NSDictionary *)_locale
  435. indent:(unsigned int)_indent
  436. {
  437. return [self descriptionWithLocale:_locale indent:_indent];
  438. }
  439. - (NSString*)descriptionWithLocale:(NSDictionary*)locale
  440. indent:(unsigned int)indent;
  441. {
  442. NSMutableString* description = [NSMutableString stringWithCString:"(\n"];
  443. unsigned int indent1 = indent + 4;
  444. NSMutableString* indentation
  445. = [NSString stringWithFormat:
  446. [NSString stringWithFormat:@"%%%dc", indent1], ' '];
  447. unsigned int count = [self count];
  448. SEL sel = @selector(appendString:);
  449. IMP imp = [description methodForSelector:sel];
  450. if(count) {
  451. id object;
  452. id stringRepresentation;
  453. unsigned int index;
  454. CREATE_AUTORELEASE_POOL(pool);
  455. object = [self objectAtIndex:0];
  456. stringRepresentation = [object propertyListStringWithLocale:locale
  457. indent:indent1];
  458. (*imp)(description, sel, indentation);
  459. (*imp)(description, sel, stringRepresentation);
  460. for (index = 1; index < count; index++) {
  461. object = [self objectAtIndex:index];
  462. stringRepresentation = [object propertyListStringWithLocale:locale
  463. indent:indent1];
  464. (*imp)(description, sel, @",\n");
  465. (*imp)(description, sel, indentation);
  466. (*imp)(description, sel, stringRepresentation);
  467. }
  468. RELEASE(pool);
  469. }
  470. (*imp)(description, sel, indent
  471. ? [NSMutableString stringWithFormat:
  472. [NSString stringWithFormat:@"\n%%%dc)", indent], ' ']
  473. : [NSMutableString stringWithCString:"\n)"]);
  474. return description;
  475. }
  476. - (NSString*)descriptionWithLocale:(NSDictionary*)locale
  477. {
  478. return [self descriptionWithLocale:locale indent:0];
  479. }
  480. - (NSString*)description
  481. {
  482. return [self descriptionWithLocale:nil indent:0];
  483. }
  484. - (NSString*)stringRepresentation
  485. {
  486. return [self descriptionWithLocale:nil indent:0];
  487. }
  488. /* Write plist to file */
  489. - (BOOL)writeToFile:(NSString*)fileName atomically:(BOOL)flag
  490. {
  491. volatile BOOL success = NO;
  492. TRY {
  493. id content = [self description];
  494. success = [content writeToFile:fileName atomically:flag];
  495. } END_TRY
  496. OTHERWISE {
  497. success = NO;
  498. } END_CATCH
  499. return success;
  500. }
  501. /* From adopted/inherited protocols */
  502. - (unsigned)hash
  503. {
  504. return [self count];
  505. }
  506. - (BOOL)isEqual:(id)anObject
  507. {
  508. if (NSArrayClass == Nil)
  509. NSArrayClass = [NSArray class];
  510. if (![anObject isKindOfClass:NSArrayClass])
  511. return NO;
  512. return [self isEqualToArray:anObject];
  513. }
  514. /* Copying */
  515. - (id)copyWithZone:(NSZone *)zone
  516. {
  517. if (NSShouldRetainWithZone(self, zone))
  518. return RETAIN(self);
  519. else {
  520. if (NSArrayClass == Nil)
  521. NSArrayClass = [NSArray class];
  522. return [[NSArrayClass allocWithZone:zone]
  523. initWithArray:self copyItems:NO];
  524. }
  525. }
  526. - (id)mutableCopyWithZone:(NSZone*)zone
  527. {
  528. if (NSMutableArrayClass == Nil)
  529. NSMutableArrayClass = [NSMutableArray class];
  530. return [[NSMutableArrayClass alloc] initWithArray:self];
  531. }
  532. /* Encoding */
  533. - (Class)classForCoder
  534. {
  535. if (NSArrayClass == Nil)
  536. NSArrayClass = [NSArray class];
  537. return NSArrayClass;
  538. }
  539. - (void)encodeWithCoder:(NSCoder*)aCoder
  540. {
  541. IMP imp = [aCoder methodForSelector:@selector(encodeObject:)];
  542. int i, count = [self count];
  543. [aCoder encodeValueOfObjCType:@encode(int) at:&count];
  544. for(i = 0; i < count; i++)
  545. (*imp)(aCoder, @selector(encodeObject:), [self objectAtIndex:i]);
  546. }
  547. - (id)initWithCoder:(NSCoder*)aDecoder
  548. {
  549. IMP imp = [aDecoder methodForSelector:@selector(decodeObject)];
  550. int i, count;
  551. [aDecoder decodeValueOfObjCType:@encode(int) at:&count];
  552. if (count > 0) {
  553. id* objects;
  554. objects = Malloc(sizeof(id) * count);
  555. {
  556. for(i = 0; i < count; i++)
  557. objects[i] = (*imp)(aDecoder, @selector(decodeObject));
  558. self = [self initWithObjects:objects count:count];
  559. }
  560. lfFree(objects);
  561. }
  562. else {
  563. self = [self init]; // empty array
  564. }
  565. return self;
  566. }
  567. @end /* NSArray */
  568. /*
  569. * Extensions to NSArray
  570. */
  571. @implementation NSArray (NSArrayExtensions)
  572. /* Sending Messages to Elements */
  573. - (void)makeObjectsPerform:(SEL)aSelector
  574. withObject:(id)anObject1 withObject:(id)anObject2
  575. {
  576. unsigned int index, count = [self count];
  577. for (index = 0; index < count; index++)
  578. [[self objectAtIndex:index]
  579. performSelector:aSelector withObject:anObject1 withObject:anObject2];
  580. }
  581. /* Deriving New Arrays */
  582. - (NSArray *)map:(SEL)aSelector
  583. {
  584. unsigned int index, count = [self count];
  585. id array;
  586. if (NSMutableArrayClass == Nil)
  587. NSMutableArrayClass = [NSMutableArray class];
  588. array = [NSMutableArrayClass arrayWithCapacity:count];
  589. for (index = 0; index < count; index++) {
  590. [array insertObject:[[self objectAtIndex:index]
  591. performSelector:aSelector]
  592. atIndex:index];
  593. }
  594. return array;
  595. }
  596. - (NSArray *)map:(SEL)aSelector with:(id)anObject
  597. {
  598. unsigned int index, count = [self count];
  599. id array;
  600. if (NSMutableArrayClass == Nil)
  601. NSMutableArrayClass = [NSMutableArray class];
  602. array = [NSMutableArrayClass arrayWithCapacity:count];
  603. for (index = 0; index < count; index++) {
  604. [array insertObject:[[self objectAtIndex:index]
  605. performSelector:aSelector withObject:anObject]
  606. atIndex:index];
  607. }
  608. return array;
  609. }
  610. - (NSArray *)map:(SEL)aSelector with:(id)anObject with:(id)otherObject;
  611. {
  612. unsigned int index, count = [self count];
  613. id array;
  614. if (NSMutableArrayClass == Nil)
  615. NSMutableArrayClass = [NSMutableArray class];
  616. array = [NSMutableArrayClass arrayWithCapacity:count];
  617. for (index = 0; index < count; index++) {
  618. [array insertObject:[[self objectAtIndex:index]
  619. performSelector:aSelector withObject:anObject withObject:otherObject]
  620. atIndex:index];
  621. }
  622. return array;
  623. }
  624. - (NSArray *)arrayWithObjectsThat:(BOOL(*)(id anObject))comparator;
  625. // Returns an array listing the receiver's elements for that comparator
  626. // function returns YES
  627. {
  628. unsigned i, m, n = [self count];
  629. id *objects;
  630. id array;
  631. objects = Malloc(sizeof(id) * n);
  632. {
  633. for (i = m = 0; i < n; i++) {
  634. id obj = [self objectAtIndex:i];
  635. if (comparator(obj))
  636. objects[m++] = obj;
  637. }
  638. array = AUTORELEASE([[[self class] alloc] initWithObjects:objects count:m]);
  639. }
  640. lfFree(objects);
  641. return array;
  642. }
  643. - (NSArray *)map:(id(*)(id anObject))function
  644. objectsThat:(BOOL(*)(id anObject))comparator;
  645. // Returns an array listing the objects returned by function applied to
  646. // objects for that comparator returns YES
  647. {
  648. unsigned i, m, n = [self count];
  649. id *objects;
  650. id array;
  651. objects = Malloc(sizeof(id) * n);
  652. {
  653. for (i = m = 0; i < n; i++) {
  654. id obj = [self objectAtIndex:i];
  655. if (comparator(obj))
  656. objects[m++] = function(obj);
  657. }
  658. array = AUTORELEASE([[[self class] alloc] initWithObjects:objects count:m]);
  659. }
  660. lfFree(objects);
  661. return array;
  662. }
  663. @end
  664. /*
  665. * NSMutableArray class
  666. *
  667. * primary methods are
  668. * init
  669. * initWithCapacity:
  670. * initWithObjects:count:
  671. * dealloc
  672. * count
  673. * objectAtIndex:
  674. * addObject:
  675. * replaceObjectAtIndex:withObject:
  676. * insertObject:atIndex:
  677. * removeObjectAtIndex:
  678. */
  679. @implementation NSMutableArray
  680. + (id)arrayWithContentsOfFile:(NSString *)fileName
  681. {
  682. id array;
  683. if ((array = [super arrayWithContentsOfFile:fileName])) {
  684. if (NSMutableArrayClass == Nil)
  685. NSMutableArrayClass = [NSMutableArray class];
  686. if (![array isKindOfClass:NSMutableArrayClass]) {
  687. array = [[NSMutableArrayClass alloc] initWithArray:array];
  688. array = AUTORELEASE(array);
  689. }
  690. }
  691. return array;
  692. }
  693. /* Creating and Initializing an NSMutableArray */
  694. + (id)allocWithZone:(NSZone*)zone
  695. {
  696. static Class NSConcreteMutableArrayClass = Nil;
  697. if (NSMutableArrayClass == Nil)
  698. NSMutableArrayClass = [NSMutableArray class];
  699. if (NSConcreteMutableArrayClass == Nil)
  700. NSConcreteMutableArrayClass = [NSConcreteMutableArray class];
  701. return NSAllocateObject( (self == NSMutableArrayClass) ?
  702. NSConcreteMutableArrayClass : (Class)self,
  703. 0, zone);
  704. }
  705. + (id)arrayWithCapacity:(unsigned int)aNumItems
  706. {
  707. return AUTORELEASE([[self alloc] initWithCapacity:aNumItems]);
  708. }
  709. - (id)init
  710. {
  711. return [self initWithCapacity:0];
  712. }
  713. - (id)initWithCapacity:(unsigned int)aNumItems
  714. {
  715. [self subclassResponsibility:_cmd];
  716. return self;
  717. }
  718. - (id)copyWithZone:(NSZone*)zone
  719. {
  720. if (NSArrayClass == Nil)
  721. NSArrayClass = [NSArray class];
  722. return [[NSArrayClass alloc] initWithArray:self copyItems:YES];
  723. }
  724. /* Adding Objects */
  725. - (void)addObject:(id)anObject
  726. {
  727. [self insertObject:anObject atIndex:[self count]];
  728. }
  729. - (void)addObjectsFromArray:(NSArray*)anotherArray
  730. {
  731. unsigned int i, j, n;
  732. n = [anotherArray count];
  733. for (i = 0, j = [self count]; i < n; i++)
  734. [self insertObject:[anotherArray objectAtIndex:i] atIndex:j++];
  735. }
  736. - (void)insertObject:(id)anObject atIndex:(unsigned int)index
  737. {
  738. [self subclassResponsibility:_cmd];
  739. }
  740. /* Removing Objects */
  741. - (void)removeAllObjects
  742. {
  743. int count = [self count];
  744. while (--count >= 0)
  745. [self removeObjectAtIndex:count];
  746. }
  747. - (void)removeLastObject
  748. {
  749. [self removeObjectAtIndex:[self count]-1];
  750. }
  751. - (void)removeObject:(id)anObject
  752. {
  753. unsigned int i, n;
  754. n = [self count];
  755. for (i = 0; i < n; i++) {
  756. id obj = [self objectAtIndex:i];
  757. if ([obj isEqual:anObject]) {
  758. [self removeObjectAtIndex:i];
  759. n--; i--;
  760. }
  761. }
  762. }
  763. - (void)removeObjectAtIndex:(unsigned int)index
  764. {
  765. [self subclassResponsibility:_cmd];
  766. }
  767. - (void)removeObjectIdenticalTo:(id)anObject
  768. {
  769. unsigned int i, n;
  770. i = n = [self count];
  771. for (i = 0; i < n; i++) {
  772. id obj = [self objectAtIndex:i];
  773. if (obj == anObject) {
  774. [self removeObjectAtIndex:i];
  775. n--; i--;
  776. }
  777. }
  778. }
  779. static int __cmp_unsigned_ints(unsigned int* i1, unsigned int* i2)
  780. {
  781. return (*i1 == *i2) ? 0 : ((*i1 < *i2) ? -1 : +1);
  782. }
  783. - (void)removeObjectsFromIndices:(unsigned int*)indices
  784. numIndices:(unsigned int)count;
  785. {
  786. unsigned int *indexes;
  787. int i;
  788. if (!count)
  789. return;
  790. indexes = Malloc(count * sizeof(unsigned int));
  791. {
  792. memcpy(indexes, indices, count * sizeof(unsigned int));
  793. qsort(indexes, count, sizeof(unsigned int),
  794. (int(*)(const void *, const void*))__cmp_unsigned_ints);
  795. for (i = count - 1; i >= 0; i++)
  796. [self removeObjectAtIndex:indexes[i]];
  797. }
  798. lfFree(indexes);
  799. }
  800. - (void)removeObjectsInArray:(NSArray*)otherArray
  801. {
  802. unsigned int i, n = [otherArray count];
  803. for (i = 0; i < n; i++)
  804. [self removeObject:[otherArray objectAtIndex:i]];
  805. }
  806. - (void)removeObject:(id)anObject inRange:(NSRange)aRange
  807. {
  808. unsigned int index;
  809. for (index = aRange.location-1; index >= aRange.location; index--)
  810. if ([anObject isEqual:[self objectAtIndex:index+aRange.location]])
  811. [self removeObjectAtIndex:index+aRange.location];
  812. }
  813. - (void)removeObjectIdenticalTo:(id)anObject inRange:(NSRange)aRange
  814. {
  815. unsigned int index;
  816. for (index = aRange.location-1; index >= aRange.location; index--)
  817. if (anObject == [self objectAtIndex:index+aRange.location])
  818. [self removeObjectAtIndex:index+aRange.location];
  819. }
  820. - (void)removeObjectsInRange:(NSRange)aRange
  821. {
  822. unsigned int index;
  823. for (index = aRange.location-1; index >= aRange.location; index--)
  824. [self removeObjectAtIndex:index+aRange.location];
  825. }
  826. /* Replacing Objects */
  827. - (void)replaceObjectAtIndex:(unsigned int)index withObject:(id)anObject
  828. {
  829. [self subclassResponsibility:_cmd];
  830. }
  831. - (void)replaceObjectsInRange:(NSRange)rRange
  832. withObjectsFromArray:(NSArray*)anArray
  833. {
  834. [self replaceObjectsInRange:rRange
  835. withObjectsFromArray:anArray
  836. range:NSMakeRange(0, [anArray count])];
  837. }
  838. - (void)replaceObjectsInRange:(NSRange)rRange
  839. withObjectsFromArray:(NSArray*)anArray range:(NSRange)aRange
  840. {
  841. unsigned int index;
  842. [self removeObjectsInRange:rRange];
  843. for (index = 0; index < aRange.length; index++)
  844. [self insertObject:[anArray objectAtIndex:aRange.location+index]
  845. atIndex:rRange.location+index];
  846. }
  847. - (void)setArray:(NSArray*)otherArray
  848. {
  849. [self removeAllObjects];
  850. [self addObjectsFromArray:otherArray];
  851. }
  852. - (void)sortUsingFunction:
  853. (int(*)(id element1, id element2, void *userData))comparator
  854. context:(void*)context
  855. {
  856. /* Shell sort algorithm taken from SortingInAction - a NeXT example */
  857. #define STRIDE_FACTOR 3 // good value for stride factor is not well-understood
  858. // 3 is a fairly good choice (Sedgewick)
  859. register int c,d, stride;
  860. BOOL found;
  861. int count;
  862. id (*objAtIdx)(id, SEL, unsigned int);
  863. if ((count = [self count]) < 2)
  864. return;
  865. objAtIdx = (void *)[self methodForSelector:@selector(objectAtIndex:)];
  866. stride = 1;
  867. while (stride <= count)
  868. stride = stride * STRIDE_FACTOR + 1;
  869. while(stride > (STRIDE_FACTOR - 1)) {
  870. // loop to sort for each value of stride
  871. stride = stride / STRIDE_FACTOR;
  872. for (c = stride; c < count; c++) {
  873. found = NO;
  874. d = c - stride;
  875. while ((d >= 0) && !found) {
  876. // move to left until correct place
  877. register id a =
  878. objAtIdx(self, @selector(objectAtIndex:), d + stride);
  879. register id b =
  880. objAtIdx(self, @selector(objectAtIndex:), d);
  881. if ((*comparator)(a, b, context) == NSOrderedAscending) {
  882. #if !LIB_FOUNDATION_BOEHM_GC
  883. [a retain];
  884. [b retain];
  885. #endif
  886. [self replaceObjectAtIndex:(d + stride) withObject:b];
  887. [self replaceObjectAtIndex:d withObject:a];
  888. d -= stride; // jump by stride factor
  889. #if !LIB_FOUNDATION_BOEHM_GC
  890. [a release];
  891. [b release];
  892. #endif
  893. }
  894. else
  895. found = YES;
  896. }
  897. }
  898. }
  899. }
  900. static int selector_compare(id elem1, id elem2, void* comparator)
  901. {
  902. return (int)(long)[elem1 performSelector:(SEL)comparator withObject:elem2];
  903. }
  904. - (void)sortUsingSelector:(SEL)comparator
  905. {
  906. [self sortUsingFunction:selector_compare context:(void*)comparator];
  907. }
  908. /* Encoding */
  909. - (Class)classForCoder
  910. {
  911. if (NSMutableArrayClass == Nil)
  912. NSMutableArrayClass = [NSMutableArray class];
  913. return NSMutableArrayClass;
  914. }
  915. @end /* NSMutableArray */
  916. /*
  917. * Extensions to NSArray
  918. */
  919. @implementation NSMutableArray (NSMutableArrayExtensions)
  920. - (void)removeObjectsFrom:(unsigned int)index count:(unsigned int)count
  921. {
  922. if (count) {
  923. while (count--)
  924. [self removeObjectAtIndex:index+count];
  925. }
  926. }
  927. - (void)removeObjectsThat:(BOOL(*)(id anObject))comparator
  928. {
  929. unsigned int index, count = [self count];
  930. for (index = 0; index < count; index++)
  931. if (comparator([self objectAtIndex:index])) {
  932. [self removeObjectAtIndex:index];
  933. index--; count--;
  934. }
  935. }
  936. @end /* NSMutableArray(NSMutableArrayExtensions) */
  937. /*
  938. * NSArrayEnumerator class
  939. */
  940. @implementation _NSArrayEnumerator
  941. - (id)initWithArray:(NSArray*)anArray reverse:(BOOL)isReverse
  942. {
  943. unsigned count = [anArray count];
  944. self->reverse = isReverse;
  945. self->array = RETAIN(anArray);
  946. self->index = (reverse)
  947. ? (count ? count - 1 : NSNotFound)
  948. : (count ? 0 : NSNotFound);
  949. return self;
  950. }
  951. - (void)dealloc
  952. {
  953. RELEASE(self->array);
  954. [super dealloc];
  955. }
  956. - (id)nextObject
  957. {
  958. id object;
  959. NSAssert(array, @"Invalid Array enumerator");
  960. if (self->index == NSNotFound)
  961. return nil;
  962. object = [self->array objectAtIndex:index];
  963. if (self->reverse) {
  964. if (self->index == 0)
  965. self->index = NSNotFound;
  966. else
  967. self->index--;
  968. } else {
  969. self->index++;
  970. if (self->index >= [array count])
  971. self->index = NSNotFound;
  972. }
  973. return object;
  974. }
  975. @end /* _NSArrayEnumerator */
  976. /*
  977. Local Variables:
  978. c-basic-offset: 4
  979. tab-width: 8
  980. End:
  981. */