lists.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /* Copyright (C) 2001-2017 Peter Selinger.
  2. This file is part of Potrace. It is free software and it is covered
  3. by the GNU General Public License. See the file COPYING for details. */
  4. #ifndef _PS_LISTS_H
  5. #define _PS_LISTS_H
  6. /* here we define some general list macros. Because they are macros,
  7. they should work on any datatype with a "->next" component. Some of
  8. them use a "hook". If elt and list are of type t* then hook is of
  9. type t**. A hook stands for an insertion point in the list, i.e.,
  10. either before the first element, or between two elements, or after
  11. the last element. If an operation "sets the hook" for an element,
  12. then the hook is set to just before the element. One can insert
  13. something at a hook. One can also unlink at a hook: this means,
  14. unlink the element just after the hook. By "to unlink", we mean the
  15. element is removed from the list, but not deleted. Thus, it and its
  16. components still need to be freed. */
  17. /* Note: these macros are somewhat experimental. Only the ones that
  18. are actually *used* have been tested. So be careful to test any
  19. that you use. Looking at the output of the preprocessor, "gcc -E"
  20. (possibly piped though "indent"), might help too. Also: these
  21. macros define some internal (local) variables that start with
  22. "_". */
  23. /* we enclose macro definitions whose body consists of more than one
  24. statement in MACRO_BEGIN and MACRO_END, rather than '{' and '}'. The
  25. reason is that we want to be able to use the macro in a context
  26. such as "if (...) macro(...); else ...". If we didn't use this obscure
  27. trick, we'd have to omit the ";" in such cases. */
  28. #define MACRO_BEGIN do {
  29. #define MACRO_END } while (0)
  30. /* ---------------------------------------------------------------------- */
  31. /* macros for singly-linked lists */
  32. /* traverse list. At the end, elt is set to NULL. */
  33. #define list_forall(elt, list) for (elt=list; elt!=NULL; elt=elt->next)
  34. /* set elt to the first element of list satisfying boolean condition
  35. c, or NULL if not found */
  36. #define list_find(elt, list, c) \
  37. MACRO_BEGIN list_forall(elt, list) if (c) break; MACRO_END
  38. /* like forall, except also set hook for elt. */
  39. #define list_forall2(elt, list, hook) \
  40. for (elt=list, hook=&list; elt!=NULL; hook=&elt->next, elt=elt->next)
  41. /* same as list_find, except also set hook for elt. */
  42. #define list_find2(elt, list, c, hook) \
  43. MACRO_BEGIN list_forall2(elt, list, hook) if (c) break; MACRO_END
  44. /* same, except only use hook. */
  45. #define _list_forall_hook(list, hook) \
  46. for (hook=&list; *hook!=NULL; hook=&(*hook)->next)
  47. /* same, except only use hook. Note: c may only refer to *hook, not elt. */
  48. #define _list_find_hook(list, c, hook) \
  49. MACRO_BEGIN _list_forall_hook(list, hook) if (c) break; MACRO_END
  50. /* insert element after hook */
  51. #define list_insert_athook(elt, hook) \
  52. MACRO_BEGIN elt->next = *hook; *hook = elt; MACRO_END
  53. /* insert element before hook */
  54. #define list_insert_beforehook(elt, hook) \
  55. MACRO_BEGIN elt->next = *hook; *hook = elt; hook=&elt->next; MACRO_END
  56. /* unlink element after hook, let elt be unlinked element, or NULL.
  57. hook remains. */
  58. #define list_unlink_athook(list, elt, hook) \
  59. MACRO_BEGIN \
  60. elt = hook ? *hook : NULL; if (elt) { *hook = elt->next; elt->next = NULL; }\
  61. MACRO_END
  62. /* unlink the specific element, if it is in the list. Otherwise, set
  63. elt to NULL */
  64. #define list_unlink(listtype, list, elt) \
  65. MACRO_BEGIN \
  66. listtype **_hook; \
  67. _list_find_hook(list, *_hook==elt, _hook); \
  68. list_unlink_athook(list, elt, _hook); \
  69. MACRO_END
  70. /* prepend elt to list */
  71. #define list_prepend(list, elt) \
  72. MACRO_BEGIN elt->next = list; list = elt; MACRO_END
  73. /* append elt to list. */
  74. #define list_append(listtype, list, elt) \
  75. MACRO_BEGIN \
  76. listtype **_hook; \
  77. _list_forall_hook(list, _hook) {} \
  78. list_insert_athook(elt, _hook); \
  79. MACRO_END
  80. /* unlink the first element that satisfies the condition. */
  81. #define list_unlink_cond(listtype, list, elt, c) \
  82. MACRO_BEGIN \
  83. listtype **_hook; \
  84. list_find2(elt, list, c, _hook); \
  85. list_unlink_athook(list, elt, _hook); \
  86. MACRO_END
  87. /* let elt be the nth element of the list, starting to count from 0.
  88. Return NULL if out of bounds. */
  89. #define list_nth(elt, list, n) \
  90. MACRO_BEGIN \
  91. int _x; /* only evaluate n once */ \
  92. for (_x=(n), elt=list; _x && elt; _x--, elt=elt->next) {} \
  93. MACRO_END
  94. /* let elt be the nth element of the list, starting to count from 0.
  95. Return NULL if out of bounds. */
  96. #define list_nth_hook(elt, list, n, hook) \
  97. MACRO_BEGIN \
  98. int _x; /* only evaluate n once */ \
  99. for (_x=(n), elt=list, hook=&list; _x && elt; _x--, hook=&elt->next, elt=elt->next) {} \
  100. MACRO_END
  101. /* set n to the length of the list */
  102. #define list_length(listtype, list, n) \
  103. MACRO_BEGIN \
  104. listtype *_elt; \
  105. n=0; \
  106. list_forall(_elt, list) \
  107. n++; \
  108. MACRO_END
  109. /* set n to the index of the first element satisfying cond, or -1 if
  110. none found. Also set elt to the element, or NULL if none found. */
  111. #define list_index(list, n, elt, c) \
  112. MACRO_BEGIN \
  113. n=0; \
  114. list_forall(elt, list) { \
  115. if (c) break; \
  116. n++; \
  117. } \
  118. if (!elt) \
  119. n=-1; \
  120. MACRO_END
  121. /* set n to the number of elements in the list that satisfy condition c */
  122. #define list_count(list, n, elt, c) \
  123. MACRO_BEGIN \
  124. n=0; \
  125. list_forall(elt, list) { \
  126. if (c) n++; \
  127. } \
  128. MACRO_END
  129. /* let elt be each element of the list, unlinked. At the end, set list=NULL. */
  130. #define list_forall_unlink(elt, list) \
  131. for (elt=list; elt ? (list=elt->next, elt->next=NULL), 1 : 0; elt=list)
  132. /* reverse a list (efficient) */
  133. #define list_reverse(listtype, list) \
  134. MACRO_BEGIN \
  135. listtype *_list1=NULL, *elt; \
  136. list_forall_unlink(elt, list) \
  137. list_prepend(_list1, elt); \
  138. list = _list1; \
  139. MACRO_END
  140. /* insert the element ELT just before the first element TMP of the
  141. list for which COND holds. Here COND must be a condition of ELT and
  142. TMP. Typical usage is to insert an element into an ordered list:
  143. for instance, list_insert_ordered(listtype, list, elt, tmp,
  144. elt->size <= tmp->size). Note: if we give a "less than or equal"
  145. condition, the new element will be inserted just before a sequence
  146. of equal elements. If we give a "less than" condition, the new
  147. element will be inserted just after a list of equal elements.
  148. Note: it is much more efficient to construct a list with
  149. list_prepend and then order it with list_merge_sort, than to
  150. construct it with list_insert_ordered. */
  151. #define list_insert_ordered(listtype, list, elt, tmp, cond) \
  152. MACRO_BEGIN \
  153. listtype **_hook; \
  154. _list_find_hook(list, (tmp=*_hook, (cond)), _hook); \
  155. list_insert_athook(elt, _hook); \
  156. MACRO_END
  157. /* sort the given list, according to the comparison condition.
  158. Typical usage is list_sort(listtype, list, a, b, a->size <
  159. b->size). Note: if we give "less than or equal" condition, each
  160. segment of equal elements will be reversed in order. If we give a
  161. "less than" condition, each segment of equal elements will retain
  162. the original order. The latter is slower but sometimes
  163. prettier. Average running time: n*n/2. */
  164. #define list_sort(listtype, list, a, b, cond) \
  165. MACRO_BEGIN \
  166. listtype *_newlist=NULL; \
  167. list_forall_unlink(a, list) \
  168. list_insert_ordered(listtype, _newlist, a, b, cond); \
  169. list = _newlist; \
  170. MACRO_END
  171. /* a much faster sort algorithm (merge sort, n log n worst case). It
  172. is required that the list type has an additional, unused next1
  173. component. Note there is no curious reversal of order of equal
  174. elements as for list_sort. */
  175. #define list_mergesort(listtype, list, a, b, cond) \
  176. MACRO_BEGIN \
  177. listtype *_elt, **_hook1; \
  178. \
  179. for (_elt=list; _elt; _elt=_elt->next1) { \
  180. _elt->next1 = _elt->next; \
  181. _elt->next = NULL; \
  182. } \
  183. do { \
  184. _hook1 = &(list); \
  185. while ((a = *_hook1) != NULL && (b = a->next1) != NULL ) { \
  186. _elt = b->next1; \
  187. _list_merge_cond(listtype, a, b, cond, *_hook1); \
  188. _hook1 = &((*_hook1)->next1); \
  189. *_hook1 = _elt; \
  190. } \
  191. } while (_hook1 != &(list)); \
  192. MACRO_END
  193. /* merge two sorted lists. Store result at &result */
  194. #define _list_merge_cond(listtype, a, b, cond, result) \
  195. MACRO_BEGIN \
  196. listtype **_hook; \
  197. _hook = &(result); \
  198. while (1) { \
  199. if (a==NULL) { \
  200. *_hook = b; \
  201. break; \
  202. } else if (b==NULL) { \
  203. *_hook = a; \
  204. break; \
  205. } else if (cond) { \
  206. *_hook = a; \
  207. _hook = &(a->next); \
  208. a = a->next; \
  209. } else { \
  210. *_hook = b; \
  211. _hook = &(b->next); \
  212. b = b->next; \
  213. } \
  214. } \
  215. MACRO_END
  216. /* ---------------------------------------------------------------------- */
  217. /* macros for doubly-linked lists */
  218. #define dlist_append(head, end, elt) \
  219. MACRO_BEGIN \
  220. elt->prev = end; \
  221. elt->next = NULL; \
  222. if (end) { \
  223. end->next = elt; \
  224. } else { \
  225. head = elt; \
  226. } \
  227. end = elt; \
  228. MACRO_END
  229. /* let elt be each element of the list, unlinked. At the end, set list=NULL. */
  230. #define dlist_forall_unlink(elt, head, end) \
  231. for (elt=head; elt ? (head=elt->next, elt->next=NULL, elt->prev=NULL), 1 : (end=NULL, 0); elt=head)
  232. /* unlink the first element of the list */
  233. #define dlist_unlink_first(head, end, elt) \
  234. MACRO_BEGIN \
  235. elt = head; \
  236. if (head) { \
  237. head = head->next; \
  238. if (head) { \
  239. head->prev = NULL; \
  240. } else { \
  241. end = NULL; \
  242. } \
  243. elt->prev = NULL; \
  244. elt->next = NULL; \
  245. } \
  246. MACRO_END
  247. #endif /* _PS_LISTS_H */