You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

293 lines
13 KiB

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