list.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. //*****************************************************************************
  2. //
  3. // list.c v1.1
  4. //
  5. // the implementation of a generic list structure.
  6. //
  7. // Jan 15/04:
  8. // Removing elements from the list while we're iterating over it can be very
  9. // dangerous. The latest revision of the list keeps track of how many iterators
  10. // are currently running overtop of us, and only actually removes items from
  11. // the list until the iterator count goes down to 0; until then, the items are
  12. // flagged as removed so they are not touched.
  13. //
  14. //*****************************************************************************
  15. #include <stdlib.h>
  16. #include <stdarg.h>
  17. #include "list.h"
  18. #ifndef FALSE
  19. #define FALSE 0
  20. #define TRUE !(FALSE)
  21. #endif
  22. typedef struct list_node {
  23. void *elem; // the data we contain
  24. struct list_node *next; // the next node in the list
  25. char removed; // has the item been removed from the list?
  26. // char == bool
  27. } LIST_NODE;
  28. struct list_iterator {
  29. struct list *L; // the list we're iterating over
  30. LIST_NODE *curr; // the current element we're iterating on
  31. };
  32. struct list {
  33. LIST_NODE *head; // first element in the list
  34. LIST_NODE *tail; // last element in the list
  35. int size; // how many elements are in the list?
  36. int iterators; // how many iterators are going over us?
  37. char remove_pending; // do we have to do a remove when the iterators die?
  38. };
  39. //
  40. // Delete a list node, and all nodes attached to it
  41. //
  42. void deleteListNode(LIST_NODE *N) {
  43. if(N->next) deleteListNode(N->next);
  44. free(N);
  45. };
  46. //
  47. // delete the list node, plus it's element using the supplied function
  48. //
  49. void deleteListNodeWith(LIST_NODE *N, void (*delete_func)(void *)) {
  50. if(N->next) deleteListNodeWith(N->next, delete_func);
  51. // we only want to delete elements that are actually in the list
  52. if(!N->removed)
  53. delete_func(N->elem);
  54. free(N);
  55. }
  56. //
  57. // Create a new list node containing the given element
  58. //
  59. LIST_NODE *newListNode(void *elem) {
  60. LIST_NODE *N = malloc(sizeof(LIST_NODE));
  61. N->elem = elem;
  62. N->next = NULL;
  63. N->removed = FALSE;
  64. return N;
  65. };
  66. //
  67. // take out all of the nodes that have been flagged as "removed"
  68. // from the list.
  69. //
  70. void listCleanRemoved(LIST *L) {
  71. // go through and kill all of the elements we removed if removes are pending
  72. if(L->remove_pending) {
  73. LIST_NODE *node = L->head;
  74. L->remove_pending = FALSE;
  75. // while our head is a removed element,
  76. // pop it off and delete the list node
  77. while(node && node->removed) {
  78. L->head = node->next;
  79. node->next = NULL;
  80. deleteListNode(node);
  81. node = L->head;
  82. }
  83. // go through the rest of the list
  84. if(node != NULL) {
  85. while(node->next != NULL) {
  86. // is our next element to be removed?
  87. if(node->next->removed) {
  88. LIST_NODE *removed = node->next;
  89. node->next = removed->next;
  90. removed->next = NULL;
  91. deleteListNode(removed);
  92. // if we just removed the last element in the list, our next
  93. // node should be NULL and we cannot keep do our next loop,
  94. // as we'll try to assign NULL to the current node
  95. if(node->next == NULL) break;
  96. }
  97. node = node->next;
  98. }
  99. }
  100. // reset the tail of our list
  101. L->tail = node;
  102. // if we have no elements left, clear our head and tail
  103. if(L->size == 0)
  104. L->head = L->tail = NULL;
  105. }
  106. }
  107. //*****************************************************************************
  108. //
  109. // List interface functions. Documentation in list.h
  110. //
  111. //*****************************************************************************
  112. LIST *newList() {
  113. LIST *L = malloc(sizeof(LIST));
  114. L->head = NULL;
  115. L->tail = NULL;
  116. L->size = 0;
  117. L->iterators = 0;
  118. L->remove_pending = FALSE;
  119. return L;
  120. };
  121. void deleteList(LIST *L) {
  122. if(L->head) deleteListNode(L->head);
  123. free(L);
  124. };
  125. void deleteListWith(LIST *L, void *func) {
  126. if(L->head) deleteListNodeWith(L->head, func);
  127. free(L);
  128. }
  129. void listPut(LIST *L, void *elem) {
  130. // if(listIn(L, elem))
  131. // return;
  132. LIST_NODE *N = newListNode(elem);
  133. N->next = L->head;
  134. L->head = N;
  135. L->size++;
  136. if(L->tail == NULL)
  137. L->tail = N;
  138. };
  139. void listQueue(LIST *L, void *elem) {
  140. // if(listIn(L, elem))
  141. // return;
  142. LIST_NODE *N = newListNode(elem);
  143. if(L->head == NULL) {
  144. L->head = N;
  145. L->tail = N;
  146. }
  147. else {
  148. L->tail->next = N;
  149. L->tail = N;
  150. }
  151. L->size++;
  152. }
  153. void *listPop(LIST *L) {
  154. return listRemoveNum(L, 0);
  155. };
  156. void listPush(LIST *L, void *elem) {
  157. listPut(L, elem);
  158. };
  159. int listIn(LIST *L, const void *elem) {
  160. LIST_NODE *N = L->head;
  161. while(N != NULL) {
  162. if(!N->removed && N->elem == elem)
  163. return TRUE;
  164. N = N->next;
  165. }
  166. return FALSE;
  167. };
  168. int listRemove(LIST *L, const void *elem) {
  169. LIST_NODE *N = L->head;
  170. // we don't have any contents
  171. if(N == NULL)
  172. return FALSE;
  173. // we first have to check if it is the head
  174. if(!N->removed && N->elem == elem) {
  175. // check to see if there's an iterator on us
  176. if(L->iterators > 0) {
  177. N->removed = TRUE;
  178. L->size--;
  179. L->remove_pending = TRUE;
  180. return TRUE;
  181. }
  182. else {
  183. L->head = N->next;
  184. N->next = NULL;
  185. deleteListNode(N);
  186. L->size--;
  187. if(L->size == 0)
  188. L->tail = NULL;
  189. return TRUE;
  190. }
  191. }
  192. // otherwise, we can check if it's another element
  193. else {
  194. while(N->next) {
  195. // we found it ... remove it now
  196. if(!N->next->removed && N->next->elem == elem) {
  197. // check to see if there's an iterator on us
  198. if(L->iterators > 0) {
  199. N->next->removed = TRUE;
  200. L->remove_pending = TRUE;
  201. L->size--;
  202. return TRUE;
  203. }
  204. else {
  205. if(N->next == L->tail)
  206. L->tail = N;
  207. LIST_NODE *tmp = N->next;
  208. N->next = tmp->next;
  209. tmp->next = NULL;
  210. deleteListNode(tmp);
  211. L->size--;
  212. return TRUE;
  213. }
  214. }
  215. N = N->next;
  216. }
  217. }
  218. // we didn't find it
  219. return FALSE;
  220. };
  221. void *listRemoveNum(LIST *L, unsigned int num) {
  222. void *elem = listGet(L, num);
  223. if(elem) listRemove(L, elem);
  224. return elem;
  225. }
  226. int listSize(LIST *L) {
  227. return L->size;
  228. }
  229. void *listGet(LIST *L, unsigned int num) {
  230. LIST_NODE *node = L->head;
  231. unsigned int i;
  232. // move up to our first non-removed node
  233. while(node && node->removed)
  234. node = node->next;
  235. for(i = 0; i < num && node; node = node->next) {
  236. if(node->removed)
  237. continue;
  238. i++;
  239. }
  240. return (node ? node->elem : NULL);
  241. }
  242. void *listHead(LIST *L) {
  243. return listGet(L, 0);
  244. }
  245. void *listTail(LIST *L) {
  246. return listGet(L, L->size-1);
  247. }
  248. int isListEmpty(LIST *L) {
  249. return (L->size == 0);
  250. }
  251. void *listGetWith(LIST *L, const void *cmpto, void *func) {
  252. int (* comparator)(const void *, const void *) = func;
  253. LIST_NODE *node = L->head;
  254. for(node = L->head; node != NULL; node = node->next) {
  255. if(node->removed)
  256. continue;
  257. if(!comparator(cmpto, node->elem))
  258. return node->elem;
  259. }
  260. return NULL;
  261. }
  262. void *listRemoveWith(LIST *L, const void *cmpto, void *func) {
  263. int (* comparator)(const void *, const void *) = func;
  264. LIST_NODE *N = L->head;
  265. // we don't have any contents
  266. if(N == NULL)
  267. return NULL;
  268. // we first have to check if it is the head
  269. if(!N->removed && !comparator(cmpto, N->elem)) {
  270. // check to see if there's an iterator on us
  271. if(L->iterators > 0) {
  272. N->removed = TRUE;
  273. L->remove_pending = TRUE;
  274. L->size--;
  275. return N->elem;
  276. }
  277. else {
  278. void *elem = N->elem;
  279. L->head = N->next;
  280. N->next = NULL;
  281. deleteListNode(N);
  282. L->size--;
  283. if(L->size == 0)
  284. L->tail = NULL;
  285. return elem;
  286. }
  287. }
  288. // otherwise, we can check if it's another element
  289. else {
  290. while(N->next) {
  291. // we found it ... remove it now
  292. if(!N->next->removed && !comparator(cmpto, N->next->elem)) {
  293. // check to see if there's an iterator on us
  294. if(L->iterators > 0) {
  295. N->next->removed = TRUE;
  296. L->remove_pending = TRUE;
  297. L->size--;
  298. return N->next->elem;
  299. }
  300. else {
  301. void *elem = N->next->elem;
  302. if(N->next == L->tail)
  303. L->tail = N;
  304. LIST_NODE *tmp = N->next;
  305. N->next = tmp->next;
  306. tmp->next = NULL;
  307. deleteListNode(tmp);
  308. L->size--;
  309. return elem;
  310. }
  311. }
  312. N = N->next;
  313. }
  314. }
  315. // we didn't find it
  316. return NULL;
  317. }
  318. void listPutWith(LIST *L, void *elem, void *func) {
  319. int (* comparator)(const void *, const void *) = func;
  320. LIST_NODE *N = L->head;
  321. // we don't have any contents, or we're lower than the
  322. // first list content then just put it at the start
  323. if(N == NULL || (!N->removed && comparator(elem, N->elem) < 0))
  324. listPut(L, elem);
  325. else {
  326. // while we've got a next element, compare ourselves to it.
  327. // if we are smaller than it, then sneak inbetween. Otherwise,
  328. // skip to the next element
  329. while(N->next != NULL) {
  330. if(!N->next->removed) {
  331. int val = comparator(elem, N->next->elem);
  332. // we're less than or equal to it... sneak in
  333. if(val <= 0) {
  334. LIST_NODE *new_node = newListNode(elem);
  335. new_node->next = N->next;
  336. N->next = new_node;
  337. L->size++;
  338. return;
  339. }
  340. }
  341. N = N->next;
  342. }
  343. // if we've gotten this far, then we need to attach ourself to the end
  344. N->next = newListNode(elem);
  345. L->tail = N->next;
  346. L->size++;
  347. }
  348. }
  349. void listSortWith(LIST *L, void *func) {
  350. // make a new list, and just pop our elements
  351. // into it while we still have 'em
  352. LIST *new_list = newList();
  353. while(listSize(L) > 0)
  354. listPutWith(new_list, listPop(L), func);
  355. // kill all of our removed nodes
  356. if(L->head) deleteListNode(L->head);
  357. L->head = new_list->head;
  358. L->tail = new_list->tail;
  359. L->size = new_list->size;
  360. // FREE ... not delete. Delete would kill the things
  361. // we just transferred over to the old list
  362. free(new_list);
  363. }
  364. LIST *listCopyWith(LIST *L, void *func) {
  365. void *(* copy_func)(void *) = func;
  366. LIST *newlist = newList();
  367. LIST_NODE *N = NULL;
  368. for(N = L->head; N; N = N->next) {
  369. if(N->removed) continue;
  370. listQueue(newlist, copy_func(N->elem));
  371. }
  372. return newlist;
  373. }
  374. void listParse(LIST *L, int n, ...) {
  375. int i;
  376. va_list args;
  377. va_start(args, n);
  378. for(i = 0; i < n; i++)
  379. *va_arg(args, void **) = listGet(L, i);
  380. va_end(args);
  381. }
  382. //*****************************************************************************
  383. //
  384. // The functions for the list iterator interface. Documentation is in list.h
  385. //
  386. //*****************************************************************************
  387. LIST_ITERATOR *newListIterator(LIST *L) {
  388. LIST_ITERATOR *I = malloc(sizeof(LIST_ITERATOR));
  389. I->L = L;
  390. I->curr = I->L->head;
  391. L->iterators++;
  392. return I;
  393. };
  394. void deleteListIterator(LIST_ITERATOR *I) {
  395. I->L->iterators--;
  396. // if we're at 0 iterators, clean the list of all removed elements
  397. if(I->L->iterators == 0)
  398. listCleanRemoved(I->L);
  399. free(I);
  400. };
  401. void *listIteratorNext(LIST_ITERATOR *I) {
  402. if(I->curr)
  403. I->curr = I->curr->next;
  404. // skip all of the removed elements
  405. while(I->curr && I->curr->removed)
  406. I->curr = I->curr->next;
  407. return (I->curr ? I->curr->elem : NULL);
  408. };
  409. // hmmm... we should really kill this function.
  410. // Just let 'em create a new iterator
  411. void listIteratorReset(LIST_ITERATOR *I) {
  412. // if we're the only iterator, take this opportunity to clean the list
  413. if(I->L->iterators == 1)
  414. listCleanRemoved(I->L);
  415. I->curr = I->L->head;
  416. };
  417. void *listIteratorCurrent(LIST_ITERATOR *I) {
  418. // hmmm... what if we're on a removed node?
  419. while(I->curr && I->curr->removed)
  420. I->curr = I->curr->next;
  421. return (I->curr ? I->curr->elem : NULL);
  422. };