PageRenderTime 147ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/src/adt/list.c

http://github.com/zedshaw/mongrel2
C | 773 lines | 438 code | 161 blank | 174 comment | 95 complexity | a45e5837426d09a3cc97f5589dbc8b43 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, Unlicense
  1. /*
  2. * List Abstract Data Type
  3. * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
  4. *
  5. * Free Software License:
  6. *
  7. * All rights are reserved by the author, with the following exceptions:
  8. * Permission is granted to freely reproduce and distribute this software,
  9. * possibly in exchange for a fee, provided that this copyright notice appears
  10. * intact. Permission is also granted to adapt this software to produce
  11. * derivative works, as long as the modified versions carry this copyright
  12. * notice and additional notices stating that the work has been modified.
  13. * This source code may be translated into executable form and incorporated
  14. * into proprietary software; there is no requirement for such software to
  15. * contain a copyright notice related to this source.
  16. *
  17. * $Id: list.c,v 1.19.2.1 2000/04/17 01:07:21 kaz Exp $
  18. * $Name: kazlib_1_20 $
  19. */
  20. #include <stdlib.h>
  21. #include <stddef.h>
  22. #include <assert.h>
  23. #define LIST_IMPLEMENTATION
  24. #include "list.h"
  25. #define next list_next
  26. #define prev list_prev
  27. #define data list_data
  28. #define pool list_pool
  29. #define fre list_free
  30. #define size list_size
  31. #define nilnode list_nilnode
  32. #define nodecount list_nodecount
  33. #define maxcount list_maxcount
  34. #define list_nil(L) (&(L)->nilnode)
  35. #define list_first_priv(L) ((L)->nilnode.next)
  36. #define list_last_priv(L) ((L)->nilnode.prev)
  37. #define lnode_next(N) ((N)->next)
  38. #define lnode_prev(N) ((N)->prev)
  39. #ifdef KAZLIB_RCSID
  40. static const char rcsid[] = "$Id: list.c,v 1.19.2.1 2000/04/17 01:07:21 kaz Exp $";
  41. #endif
  42. /*
  43. * Initialize a list object supplied by the client such that it becomes a valid
  44. * empty list. If the list is to be ``unbounded'', the maxcount should be
  45. * specified as LISTCOUNT_T_MAX, or, alternately, as -1. The value zero
  46. * is not permitted.
  47. */
  48. list_t *list_init(list_t *list, listcount_t maxcount)
  49. {
  50. assert (maxcount != 0);
  51. list->nilnode.next = &list->nilnode;
  52. list->nilnode.prev = &list->nilnode;
  53. list->nodecount = 0;
  54. list->maxcount = maxcount;
  55. return list;
  56. }
  57. /*
  58. * Dynamically allocate a list object using malloc(), and initialize it so that
  59. * it is a valid empty list. If the list is to be ``unbounded'', the maxcount
  60. * should be specified as LISTCOUNT_T_MAX, or, alternately, as -1.
  61. */
  62. list_t *list_create(listcount_t maxcount)
  63. {
  64. list_t *new = malloc(sizeof *new);
  65. if (new) {
  66. assert (maxcount != 0);
  67. new->nilnode.next = &new->nilnode;
  68. new->nilnode.prev = &new->nilnode;
  69. new->nodecount = 0;
  70. new->maxcount = maxcount;
  71. }
  72. return new;
  73. }
  74. /*
  75. * Destroy a dynamically allocated list object.
  76. * The client must remove the nodes first.
  77. */
  78. void list_destroy(list_t *list)
  79. {
  80. assert (list_isempty(list));
  81. free(list);
  82. }
  83. /*
  84. * Free all of the nodes of a list. The list must contain only
  85. * dynamically allocated nodes. After this call, the list
  86. * is empty.
  87. */
  88. void list_destroy_nodes(list_t *list)
  89. {
  90. lnode_t *lnode = list_first_priv(list), *nil = list_nil(list), *tmp;
  91. while (lnode != nil) {
  92. tmp = lnode->next;
  93. lnode->next = NULL;
  94. lnode->prev = NULL;
  95. lnode_destroy(lnode);
  96. lnode = tmp;
  97. }
  98. list_init(list, list->maxcount);
  99. }
  100. /*
  101. * Return all of the nodes of a list to a node pool. The nodes in
  102. * the list must all have come from the same pool.
  103. */
  104. void list_return_nodes(list_t *list, lnodepool_t *pool)
  105. {
  106. lnode_t *lnode = list_first_priv(list), *tmp, *nil = list_nil(list);
  107. while (lnode != nil) {
  108. tmp = lnode->next;
  109. lnode->next = NULL;
  110. lnode->prev = NULL;
  111. lnode_return(pool, lnode);
  112. lnode = tmp;
  113. }
  114. list_init(list, list->maxcount);
  115. }
  116. /*
  117. * Insert the node ``new'' into the list immediately after ``this'' node.
  118. */
  119. void list_ins_after(list_t *list, lnode_t *new, lnode_t *this)
  120. {
  121. lnode_t *that = this->next;
  122. assert (new != NULL);
  123. assert (!list_contains(list, new));
  124. assert (!lnode_is_in_a_list(new));
  125. assert (this == list_nil(list) || list_contains(list, this));
  126. assert (list->nodecount + 1 > list->nodecount);
  127. new->prev = this;
  128. new->next = that;
  129. that->prev = new;
  130. this->next = new;
  131. list->nodecount++;
  132. assert (list->nodecount <= list->maxcount);
  133. }
  134. /*
  135. * Insert the node ``new'' into the list immediately before ``this'' node.
  136. */
  137. void list_ins_before(list_t *list, lnode_t *new, lnode_t *this)
  138. {
  139. lnode_t *that = this->prev;
  140. assert (new != NULL);
  141. assert (!list_contains(list, new));
  142. assert (!lnode_is_in_a_list(new));
  143. assert (this == list_nil(list) || list_contains(list, this));
  144. assert (list->nodecount + 1 > list->nodecount);
  145. new->next = this;
  146. new->prev = that;
  147. that->next = new;
  148. this->prev = new;
  149. list->nodecount++;
  150. assert (list->nodecount <= list->maxcount);
  151. }
  152. /*
  153. * Delete the given node from the list.
  154. */
  155. lnode_t *list_delete(list_t *list, lnode_t *del)
  156. {
  157. lnode_t *next = del->next;
  158. lnode_t *prev = del->prev;
  159. assert (list_contains(list, del));
  160. prev->next = next;
  161. next->prev = prev;
  162. list->nodecount--;
  163. del->next = del->prev = NULL;
  164. return del;
  165. }
  166. /*
  167. * For each node in the list, execute the given function. The list,
  168. * current node and the given context pointer are passed on each
  169. * call to the function.
  170. */
  171. void list_process(list_t *list, void *context,
  172. void (* function)(list_t *list, lnode_t *lnode, void *context))
  173. {
  174. lnode_t *node = list_first_priv(list), *next, *nil = list_nil(list);
  175. while (node != nil) {
  176. /* check for callback function deleting */
  177. /* the next node from under us */
  178. assert (list_contains(list, node));
  179. next = node->next;
  180. function(list, node, context);
  181. node = next;
  182. }
  183. }
  184. /*
  185. * Dynamically allocate a list node and assign it the given piece of data.
  186. */
  187. lnode_t *lnode_create(void *data)
  188. {
  189. lnode_t *new = malloc(sizeof *new);
  190. if (new) {
  191. new->data = data;
  192. new->next = NULL;
  193. new->prev = NULL;
  194. }
  195. return new;
  196. }
  197. /*
  198. * Initialize a user-supplied lnode.
  199. */
  200. lnode_t *lnode_init(lnode_t *lnode, void *data)
  201. {
  202. lnode->data = data;
  203. lnode->next = NULL;
  204. lnode->prev = NULL;
  205. return lnode;
  206. }
  207. /*
  208. * Destroy a dynamically allocated node.
  209. */
  210. void lnode_destroy(lnode_t *lnode)
  211. {
  212. assert (!lnode_is_in_a_list(lnode));
  213. free(lnode);
  214. }
  215. /*
  216. * Initialize a node pool object to use a user-supplied set of nodes.
  217. * The ``nodes'' pointer refers to an array of lnode_t objects, containing
  218. * ``n'' elements.
  219. */
  220. lnodepool_t *lnode_pool_init(lnodepool_t *pool, lnode_t *nodes, listcount_t n)
  221. {
  222. listcount_t i;
  223. assert (n != 0);
  224. pool->pool = nodes;
  225. pool->fre = nodes;
  226. pool->size = n;
  227. for (i = 0; i < n - 1; i++) {
  228. nodes[i].next = nodes + i + 1;
  229. }
  230. nodes[i].next = NULL;
  231. nodes[i].prev = nodes; /* to make sure node is marked ``on list'' */
  232. return pool;
  233. }
  234. /*
  235. * Create a dynamically allocated pool of n nodes.
  236. */
  237. lnodepool_t *lnode_pool_create(listcount_t n)
  238. {
  239. lnodepool_t *pool;
  240. lnode_t *nodes;
  241. assert (n != 0);
  242. pool = malloc(sizeof *pool);
  243. if (!pool)
  244. return NULL;
  245. nodes = malloc(n * sizeof *nodes);
  246. if (!nodes) {
  247. free(pool);
  248. return NULL;
  249. }
  250. lnode_pool_init(pool, nodes, n);
  251. return pool;
  252. }
  253. /*
  254. * Determine whether the given pool is from this pool.
  255. */
  256. int lnode_pool_isfrom(lnodepool_t *pool, lnode_t *node)
  257. {
  258. listcount_t i;
  259. /* this is carefully coded this way because ANSI C forbids pointers
  260. to different objects from being subtracted or compared other
  261. than for exact equality */
  262. for (i = 0; i < pool->size; i++) {
  263. if (pool->pool + i == node)
  264. return 1;
  265. }
  266. return 0;
  267. }
  268. /*
  269. * Destroy a dynamically allocated pool of nodes.
  270. */
  271. void lnode_pool_destroy(lnodepool_t *p)
  272. {
  273. free(p->pool);
  274. free(p);
  275. }
  276. /*
  277. * Borrow a node from a node pool. Returns a null pointer if the pool
  278. * is exhausted.
  279. */
  280. lnode_t *lnode_borrow(lnodepool_t *pool, void *data)
  281. {
  282. lnode_t *new = pool->fre;
  283. if (new) {
  284. pool->fre = new->next;
  285. new->data = data;
  286. new->next = NULL;
  287. new->prev = NULL;
  288. }
  289. return new;
  290. }
  291. /*
  292. * Return a node to a node pool. A node must be returned to the pool
  293. * from which it came.
  294. */
  295. void lnode_return(lnodepool_t *pool, lnode_t *node)
  296. {
  297. assert (lnode_pool_isfrom(pool, node));
  298. assert (!lnode_is_in_a_list(node));
  299. node->next = pool->fre;
  300. node->prev = node;
  301. pool->fre = node;
  302. }
  303. /*
  304. * Determine whether the given list contains the given node.
  305. * According to this function, a list does not contain its nilnode.
  306. */
  307. int list_contains(list_t *list, lnode_t *node)
  308. {
  309. lnode_t *n, *nil = list_nil(list);
  310. for (n = list_first_priv(list); n != nil; n = lnode_next(n)) {
  311. if (node == n)
  312. return 1;
  313. }
  314. return 0;
  315. }
  316. /*
  317. * A more generalized variant of list_transfer. This one removes a
  318. * ``slice'' from the source list and appends it to the destination
  319. * list.
  320. */
  321. void list_extract(list_t *dest, list_t *source, lnode_t *first, lnode_t *last)
  322. {
  323. listcount_t moved = 1;
  324. assert (first == NULL || list_contains(source, first));
  325. assert (last == NULL || list_contains(source, last));
  326. if (first == NULL || last == NULL)
  327. return;
  328. /* adjust the destination list so that the slice is spliced out */
  329. first->prev->next = last->next;
  330. last->next->prev = first->prev;
  331. /* graft the splice at the end of the dest list */
  332. last->next = &dest->nilnode;
  333. first->prev = dest->nilnode.prev;
  334. dest->nilnode.prev->next = first;
  335. dest->nilnode.prev = last;
  336. while (first != last) {
  337. first = first->next;
  338. assert (first != list_nil(source)); /* oops, last before first! */
  339. moved++;
  340. }
  341. /* assert no overflows */
  342. assert (source->nodecount - moved <= source->nodecount);
  343. assert (dest->nodecount + moved >= dest->nodecount);
  344. /* assert no weirdness */
  345. assert (moved <= source->nodecount);
  346. source->nodecount -= moved;
  347. dest->nodecount += moved;
  348. /* assert list sanity */
  349. assert (list_verify(source));
  350. assert (list_verify(dest));
  351. }
  352. /*
  353. * Split off a trailing sequence of nodes from the source list and relocate
  354. * them to the tail of the destination list. The trailing sequence begins
  355. * with node ``first'' and terminates with the last node of the source
  356. * list. The nodes are added to the end of the new list in their original
  357. * order.
  358. */
  359. void list_transfer(list_t *dest, list_t *source, lnode_t *first)
  360. {
  361. listcount_t moved = 1;
  362. lnode_t *last;
  363. assert (first == NULL || list_contains(source, first));
  364. if (first == NULL)
  365. return;
  366. last = source->nilnode.prev;
  367. source->nilnode.prev = first->prev;
  368. first->prev->next = &source->nilnode;
  369. last->next = &dest->nilnode;
  370. first->prev = dest->nilnode.prev;
  371. dest->nilnode.prev->next = first;
  372. dest->nilnode.prev = last;
  373. while (first != last) {
  374. first = first->next;
  375. moved++;
  376. }
  377. /* assert no overflows */
  378. assert (source->nodecount - moved <= source->nodecount);
  379. assert (dest->nodecount + moved >= dest->nodecount);
  380. /* assert no weirdness */
  381. assert (moved <= source->nodecount);
  382. source->nodecount -= moved;
  383. dest->nodecount += moved;
  384. /* assert list sanity */
  385. assert (list_verify(source));
  386. assert (list_verify(dest));
  387. }
  388. void list_merge(list_t *dest, list_t *sour,
  389. int compare (const void *, const void *))
  390. {
  391. lnode_t *dn, *sn, *tn;
  392. lnode_t *d_nil = list_nil(dest), *s_nil = list_nil(sour);
  393. /* Nothing to do if source and destination list are the same. */
  394. if (dest == sour)
  395. return;
  396. /* overflow check */
  397. assert (list_count(sour) + list_count(dest) >= list_count(sour));
  398. /* lists must be sorted */
  399. assert (list_is_sorted(sour, compare));
  400. assert (list_is_sorted(dest, compare));
  401. dn = list_first_priv(dest);
  402. sn = list_first_priv(sour);
  403. while (dn != d_nil && sn != s_nil) {
  404. if (compare(lnode_get(dn), lnode_get(sn)) >= 0) {
  405. tn = lnode_next(sn);
  406. list_delete(sour, sn);
  407. list_ins_before(dest, sn, dn);
  408. sn = tn;
  409. } else {
  410. dn = lnode_next(dn);
  411. }
  412. }
  413. if (dn != d_nil)
  414. return;
  415. if (sn != s_nil)
  416. list_transfer(dest, sour, sn);
  417. }
  418. void list_sort(list_t *list, int compare(const void *, const void *))
  419. {
  420. list_t extra;
  421. listcount_t middle;
  422. lnode_t *node;
  423. if (list_count(list) > 1) {
  424. middle = list_count(list) / 2;
  425. node = list_first_priv(list);
  426. list_init(&extra, list_count(list) - middle);
  427. while (middle--)
  428. node = lnode_next(node);
  429. list_transfer(&extra, list, node);
  430. list_sort(list, compare);
  431. list_sort(&extra, compare);
  432. list_merge(list, &extra, compare);
  433. }
  434. assert (list_is_sorted(list, compare));
  435. }
  436. lnode_t *list_find(list_t *list, const void *key, int compare(const void *, const void *))
  437. {
  438. lnode_t *node;
  439. for (node = list_first_priv(list); node != list_nil(list); node = node->next) {
  440. if (compare(lnode_get(node), key) == 0)
  441. return node;
  442. }
  443. return 0;
  444. }
  445. /*
  446. * Return 1 if the list is in sorted order, 0 otherwise
  447. */
  448. int list_is_sorted(list_t *list, int compare(const void *, const void *))
  449. {
  450. lnode_t *node, *next, *nil;
  451. next = nil = list_nil(list);
  452. node = list_first_priv(list);
  453. if (node != nil)
  454. next = lnode_next(node);
  455. for (; next != nil; node = next, next = lnode_next(next)) {
  456. if (compare(lnode_get(node), lnode_get(next)) > 0)
  457. return 0;
  458. }
  459. return 1;
  460. }
  461. /*
  462. * Get rid of macro functions definitions so they don't interfere
  463. * with the actual definitions
  464. */
  465. #undef list_isempty
  466. #undef list_isfull
  467. #undef lnode_pool_isempty
  468. #undef list_append
  469. #undef list_prepend
  470. #undef list_first
  471. #undef list_last
  472. #undef list_next
  473. #undef list_prev
  474. #undef list_count
  475. #undef list_del_first
  476. #undef list_del_last
  477. #undef lnode_put
  478. #undef lnode_get
  479. /*
  480. * Return 1 if the list is empty, 0 otherwise
  481. */
  482. int list_isempty(list_t *list)
  483. {
  484. return list->nodecount == 0;
  485. }
  486. /*
  487. * Return 1 if the list is full, 0 otherwise
  488. * Permitted only on bounded lists.
  489. */
  490. int list_isfull(list_t *list)
  491. {
  492. return list->nodecount == list->maxcount;
  493. }
  494. /*
  495. * Check if the node pool is empty.
  496. */
  497. int lnode_pool_isempty(lnodepool_t *pool)
  498. {
  499. return (pool->fre == NULL);
  500. }
  501. /*
  502. * Add the given node at the end of the list
  503. */
  504. void list_append(list_t *list, lnode_t *node)
  505. {
  506. list_ins_before(list, node, &list->nilnode);
  507. }
  508. /*
  509. * Add the given node at the beginning of the list.
  510. */
  511. void list_prepend(list_t *list, lnode_t *node)
  512. {
  513. list_ins_after(list, node, &list->nilnode);
  514. }
  515. /*
  516. * Retrieve the first node of the list
  517. */
  518. lnode_t *list_first(list_t *list)
  519. {
  520. if (list->nilnode.next == &list->nilnode)
  521. return NULL;
  522. return list->nilnode.next;
  523. }
  524. /*
  525. * Retrieve the last node of the list
  526. */
  527. lnode_t *list_last(list_t *list)
  528. {
  529. if (list->nilnode.prev == &list->nilnode)
  530. return NULL;
  531. return list->nilnode.prev;
  532. }
  533. /*
  534. * Retrieve the count of nodes in the list
  535. */
  536. listcount_t list_count(list_t *list)
  537. {
  538. return list->nodecount;
  539. }
  540. /*
  541. * Remove the first node from the list and return it.
  542. */
  543. lnode_t *list_del_first(list_t *list)
  544. {
  545. return list_delete(list, list->nilnode.next);
  546. }
  547. /*
  548. * Remove the last node from the list and return it.
  549. */
  550. lnode_t *list_del_last(list_t *list)
  551. {
  552. return list_delete(list, list->nilnode.prev);
  553. }
  554. /*
  555. * Associate a data item with the given node.
  556. */
  557. void lnode_put(lnode_t *lnode, void *data)
  558. {
  559. lnode->data = data;
  560. }
  561. /*
  562. * Retrieve the data item associated with the node.
  563. */
  564. void *lnode_get(lnode_t *lnode)
  565. {
  566. return lnode->data;
  567. }
  568. /*
  569. * Retrieve the node's successor. If there is no successor,
  570. * NULL is returned.
  571. */
  572. lnode_t *list_next(list_t *list, lnode_t *lnode)
  573. {
  574. assert (list_contains(list, lnode));
  575. if (lnode->next == list_nil(list))
  576. return NULL;
  577. return lnode->next;
  578. }
  579. /*
  580. * Retrieve the node's predecessor. See comment for lnode_next().
  581. */
  582. lnode_t *list_prev(list_t *list, lnode_t *lnode)
  583. {
  584. assert (list_contains(list, lnode));
  585. if (lnode->prev == list_nil(list))
  586. return NULL;
  587. return lnode->prev;
  588. }
  589. /*
  590. * Return 1 if the lnode is in some list, otherwise return 0.
  591. */
  592. int lnode_is_in_a_list(lnode_t *lnode)
  593. {
  594. return (lnode->next != NULL || lnode->prev != NULL);
  595. }
  596. int list_verify(list_t *list)
  597. {
  598. lnode_t *node = list_first_priv(list), *nil = list_nil(list);
  599. listcount_t count = list_count(list);
  600. if (node->prev != nil)
  601. return 0;
  602. if (count > list->maxcount)
  603. return 0;
  604. while (node != nil && count--) {
  605. if (node->next->prev != node)
  606. return 0;
  607. node = node->next;
  608. }
  609. if (count != 0 || node != nil)
  610. return 0;
  611. return 1;
  612. }