PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/list/List.m

http://github.com/jimm/subjective_c
Objective C | 428 lines | 211 code | 72 blank | 145 comment | 62 complexity | 34d15aabdd4547b1e89930ca79974d4a MD5 | raw file
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "List.h"
  4. #define INITIAL_SIZE 4
  5. @implementation List
  6. /*
  7. * Initializes the receiver, a new List object, by allocating enough memory for
  8. * it to hold numSlots objects. Returns self.
  9. *
  10. * This method is the designated initializer for the class. It should be used
  11. * immediately after memory for the List has been allocated and before any
  12. * objects have been assigned to it; it shouldn't be used to reinitialize a
  13. * List that's already in use.
  14. */
  15. - initCount: (int)numSlots
  16. {
  17. [super init];
  18. return [self setAvailableCapacity: numSlots];
  19. }
  20. /*
  21. * Deallocates the List object and the memory it allocated for the array of
  22. * object ids. However, the objects themselves aren't freed.
  23. */
  24. - free
  25. {
  26. if (data)
  27. free(data);
  28. n_elements = n_allocated = 0;
  29. return [super free];
  30. }
  31. /*
  32. * Removes every object from the List, sends each one of them a free message,
  33. * and returns self. The List object itself isn't freed and its current
  34. * capacity isn't altered.
  35. *
  36. * The methods that free the objects shouldn't have the side effect of
  37. * modifying the List.
  38. */
  39. - freeObjects
  40. {
  41. int index;
  42. for (index = 0; index < n_elements; ++index)
  43. [data[index] free];
  44. n_elements = 0;
  45. return self;
  46. }
  47. /*
  48. * Compares the receiving List to anObject. If anObject is a List with exactly
  49. * the same contents as the receiver, this method returns YES. If not, it
  50. * returns NO.
  51. *
  52. * Two Lists have the same contents if they each hold the same number of
  53. * objects and the ids in each List are identical and occur in the same order.
  54. *
  55. * NOTE: Should check class of anObject to see if it's a (sub)class of List.
  56. */
  57. - (BOOL)isEqual: anObject
  58. {
  59. int index;
  60. if (anObject == nil || ![anObject isKindOf: ListClass] ||
  61. n_elements != [anObject count])
  62. return NO;
  63. for (index = 0; index < n_elements; ++index)
  64. if (data[index] != ((List *)anObject)->data[index])
  65. return NO;
  66. return YES;
  67. }
  68. /*
  69. * Inserts anObject at the end of the List, and returns self. However, if
  70. * anObject is nil, nothing is inserted and nil is returned.
  71. */
  72. - addObject: anObject
  73. {
  74. if (anObject == nil)
  75. return nil;
  76. if (n_elements >= n_allocated) {
  77. if ([self setAvailableCapacity: n_allocated * 2] == nil)
  78. return nil;
  79. }
  80. data[n_elements++] = anObject;
  81. return self;
  82. }
  83. /*
  84. * Returns the maximum number of objects that can be stored in the List without
  85. * allocating more memory for it. When new memory is allocated, it's taken
  86. * from the same zone that was specified when the List was created.
  87. */
  88. - (int)capacity
  89. {
  90. return n_allocated;
  91. }
  92. /*
  93. * Sets the storage capacity of the List to at least numSlots objects and
  94. * returns self. However, if the List already contains more than numSlots
  95. * objects (if the count method returns a number greater than numSlots), its
  96. * capacity is left unchanged and nil is returned.
  97. */
  98. - setAvailableCapacity: (int)numSlots
  99. {
  100. int newNAlloc;
  101. size_t size;
  102. if (n_allocated > numSlots)
  103. return nil;
  104. newNAlloc = (n_allocated == 0) ? INITIAL_SIZE : n_allocated;
  105. while (newNAlloc < numSlots)
  106. newNAlloc *= 2;
  107. size = (size_t)(newNAlloc * sizeof(id));
  108. if (data == NULL)
  109. data = malloc(size);
  110. else
  111. data = realloc(data, size);
  112. n_allocated = newNAlloc;
  113. return self;
  114. }
  115. /*
  116. * Returns the number of objects currently in the List.
  117. */
  118. - (int)count
  119. {
  120. return n_elements;
  121. }
  122. /*
  123. * Returns the id of the object located at slot index, or nil if index is
  124. * beyond the end of the List.
  125. */
  126. - objectAt: (int)index
  127. {
  128. if (index >= n_elements)
  129. return nil;
  130. return data[index];
  131. }
  132. /*
  133. * Returns the last object in the List, or nil if there are no objects in the
  134. * List. This method doesn't remove the object that's returned.
  135. */
  136. - lastObject
  137. {
  138. if (n_elements > 0)
  139. return data[n_elements - 1];
  140. else
  141. return nil;
  142. }
  143. /*
  144. * Inserts anObject into the List at index, moving objects down one slot to
  145. * make room. If index equals the value returned by the count method, anObject
  146. * is inserted at the end of the List. However, the insertion fails if index
  147. * is greater than the value returned by count or anObject is nil.
  148. *
  149. * If anObject is successfully inserted into the List, this method returns
  150. * self. If not, it returns nil.
  151. */
  152. - insertObject: anObject at: (int)index
  153. {
  154. int i;
  155. if (index > n_elements || anObject == nil)
  156. return nil;
  157. if (index == n_elements)
  158. return [self addObject: anObject];
  159. for (i = n_elements; i > index; --i)
  160. data[i] = data[i - 1];
  161. ++n_elements;
  162. data[index] = anObject;
  163. return self;
  164. }
  165. /*
  166. * Removes the object located at index and returns it. If there's no object at
  167. * index, this method returns nil.
  168. *
  169. * The positions of the remaining objects in the List are adjusted so there's
  170. * no gap.
  171. */
  172. - removeObjectAt: (int)index
  173. {
  174. id obj;
  175. if (n_elements == 0 || index >= n_elements)
  176. return nil;
  177. obj = data[index];
  178. for (--n_elements; index < n_elements; ++index)
  179. data[index] = data[index + 1];
  180. return obj;
  181. }
  182. /*
  183. * Removes the object occupying the last position in the List and returns it.
  184. * If there are no objects in the List, this method returns nil.
  185. */
  186. - removeLastObject
  187. {
  188. id obj;
  189. if (n_elements == 0)
  190. return nil;
  191. obj = data[--n_elements];
  192. return obj;
  193. }
  194. /*
  195. * Returns the object at index after replacing it with newObject. If there's
  196. * no object at index or newObject is nil, nothing is replaced and nil is
  197. * returned.
  198. */
  199. - replaceObjectAt: (int)index with: newObject
  200. {
  201. id obj;
  202. if (index >= n_elements || newObject == nil)
  203. return nil;
  204. obj = data[index];
  205. data[index] = newObject;
  206. return obj;
  207. }
  208. /*
  209. * Inserts all the objects in otherList at the end of the receiving List, and
  210. * returns self. The ordering of the objects is maintained.
  211. */
  212. - appendList: (List *)otherList
  213. {
  214. int index;
  215. if (![otherList isKindOf: ListClass])
  216. return nil;
  217. for (index = 0; index < [otherList count]; ++index)
  218. [self addObject: [otherList objectAt: index]];
  219. return self;
  220. }
  221. /*
  222. * Returns the index of the first occurrence of anObject in the List, or
  223. * NOT_IN_LIST if anObject isn't in the List.
  224. */
  225. - (int)indexOf: anObject
  226. {
  227. int index;
  228. if (anObject == nil)
  229. return NOT_IN_LIST;
  230. for (index = 0; index < n_elements; ++index)
  231. if (data[index] == anObject)
  232. return index;
  233. return NOT_IN_LIST;
  234. }
  235. /*
  236. * Inserts anObject at the end of the List and returns self, provided that
  237. * anObject isn't already in the List. If anObject is in the List, it won't be
  238. * inserted, but self is still returned.
  239. *
  240. * If anObject is nil, nothing is inserted and nil is returned.
  241. */
  242. - addObjectIfAbsent: anObject
  243. {
  244. if (anObject == nil)
  245. return nil;
  246. if ([self indexOf: anObject] == NOT_IN_LIST) {
  247. if (n_elements >= n_allocated) {
  248. if ([self setAvailableCapacity: n_allocated * 2] == nil)
  249. return nil;
  250. }
  251. data[n_elements++] = anObject;
  252. }
  253. return self;
  254. }
  255. /*
  256. * Removes the first occurrence of anObject from the List, and returns it. If
  257. * anObject isn't in the List, this method returns nil.
  258. *
  259. * The positions of the remaining objects in the List are adjusted so there's
  260. * no gap.
  261. */
  262. - removeObject: anObject
  263. {
  264. int index = [self indexOf: anObject];
  265. if (index == NOT_IN_LIST)
  266. return nil;
  267. return [self removeObjectAt: index];
  268. }
  269. /*
  270. * Replaces the first occurrence of anObject in the List with newObject, and
  271. * returns anObject. However, if newObject is nil or anObject isn't in the
  272. * List, nothing is replaced and nil is returned.
  273. */
  274. - replaceObject: anObject with: newObject
  275. {
  276. int index = [self indexOf: anObject];
  277. if (index == NOT_IN_LIST || newObject == nil)
  278. return nil;
  279. data[index] = newObject;
  280. return anObject;
  281. }
  282. /*
  283. * Empties the List of all its objects without freeing them, and returns self.
  284. * The current capacity of the List isn't changed.
  285. */
  286. - empty
  287. {
  288. n_elements = 0;
  289. return self;
  290. }
  291. /*
  292. * Sends an aSelector message to each object in the List in reverse order
  293. * (starting with the last object and continuing backwards through the List to
  294. * the first object), and returns self. The aSelector method must be one that
  295. * takes no arguments. It shouldn't have the side effect of modifying the
  296. * List.
  297. */
  298. - makeObjectsPerform: (SEL)aSelector
  299. {
  300. int index = [self count];
  301. if (index == 0)
  302. return self;
  303. --index;
  304. do {
  305. [[self objectAt: index] perform: aSelector];
  306. } while (index--);
  307. return self;
  308. }
  309. /*
  310. * Sends an aSelector message to each object in the List in reverse order
  311. * (starting with the last object and continuing backwards through the List to
  312. * the first object), and returns self. The message is sent each time with
  313. * anObject as an argument, so the aSelector method must be one that takes a
  314. * single argument of type id. The aSelector method shouldn't, as a side
  315. * effect, modify the List.
  316. */
  317. - makeObjectsPerform: (SEL)aSelector with: anObject
  318. {
  319. int index = [self count];
  320. if (index == 0)
  321. return self;
  322. --index;
  323. do {
  324. [[self objectAt: index] perform: aSelector with: anObject];
  325. } while (index--);
  326. return self;
  327. }
  328. #if 0
  329. /*
  330. * Reads the List and all the objects it contains from the typed stream stream.
  331. */
  332. - read: (NXTypedStream *)stream
  333. {
  334. }
  335. /*
  336. * Writes the List, including all the objects it contains, to the typed stream
  337. * stream.
  338. */
  339. - write:(NXTypedStream *)stream
  340. {
  341. }
  342. /*
  343. * Returns a new List object with the same contents as the receiver. The
  344. * objects in the List aren't copied; therefore, both Lists contain pointers
  345. * to the same set of objects. Memory for the new List is allocated from zone.
  346. */
  347. - copyFromZone:(NXZone *)zone
  348. {
  349. }
  350. #endif
  351. @end
  352. /*
  353. ;;; Local Variables: ***
  354. ;;; tab-width:4 ***
  355. ;;; End: ***
  356. */