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.

333 lines
15 KiB

  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 \
  29. do \
  30. {
  31. #define MACRO_END \
  32. } \
  33. while( 0 )
  34. /* ---------------------------------------------------------------------- */
  35. /* macros for singly-linked lists */
  36. /* traverse list. At the end, elt is set to NULL. */
  37. #define list_forall( elt, list ) for( elt = list; elt != NULL; elt = elt->next )
  38. /* set elt to the first element of list satisfying boolean condition
  39. * c, or NULL if not found */
  40. #define list_find( elt, list, c ) \
  41. MACRO_BEGIN list_forall( elt, list ) if( c ) \
  42. break; \
  43. MACRO_END
  44. /* like forall, except also set hook for elt. */
  45. #define list_forall2( elt, list, hook ) \
  46. for( elt = list, hook = &list; elt != NULL; hook = &elt->next, elt = elt->next )
  47. /* same as list_find, except also set hook for elt. */
  48. #define list_find2( elt, list, c, hook ) \
  49. MACRO_BEGIN list_forall2( elt, list, hook ) if( c ) \
  50. break; \
  51. MACRO_END
  52. /* same, except only use hook. */
  53. #define _list_forall_hook( list, hook ) for( hook = &list; *hook != NULL; hook = &( *hook )->next )
  54. /* same, except only use hook. Note: c may only refer to *hook, not elt. */
  55. #define _list_find_hook( list, c, hook ) \
  56. MACRO_BEGIN _list_forall_hook( list, hook ) if( c ) \
  57. break; \
  58. MACRO_END
  59. /* insert element after hook */
  60. #define list_insert_athook( elt, hook ) \
  61. MACRO_BEGIN elt->next = *hook; \
  62. *hook = elt; \
  63. MACRO_END
  64. /* insert element before hook */
  65. #define list_insert_beforehook( elt, hook ) \
  66. MACRO_BEGIN elt->next = *hook; \
  67. *hook = elt; \
  68. hook = &elt->next; \
  69. MACRO_END
  70. /* unlink element after hook, let elt be unlinked element, or NULL.
  71. * hook remains. */
  72. #define list_unlink_athook( list, elt, hook ) \
  73. MACRO_BEGIN \
  74. elt = hook ? *hook : NULL; \
  75. if( elt ) \
  76. { \
  77. *hook = elt->next; \
  78. elt->next = NULL; \
  79. } \
  80. MACRO_END
  81. /* unlink the specific element, if it is in the list. Otherwise, set
  82. * elt to NULL */
  83. #define list_unlink( listtype, list, elt ) \
  84. MACRO_BEGIN \
  85. listtype * *_hook; \
  86. _list_find_hook( list, *_hook == elt, _hook ); \
  87. list_unlink_athook( list, elt, _hook ); \
  88. MACRO_END
  89. /* prepend elt to list */
  90. #define list_prepend( list, elt ) \
  91. MACRO_BEGIN elt->next = list; \
  92. list = elt; \
  93. MACRO_END
  94. /* append elt to list. */
  95. #define list_append( listtype, list, elt ) \
  96. MACRO_BEGIN \
  97. listtype * *_hook; \
  98. _list_forall_hook( list, _hook ) \
  99. { \
  100. } \
  101. list_insert_athook( elt, _hook ); \
  102. MACRO_END
  103. /* unlink the first element that satisfies the condition. */
  104. #define list_unlink_cond( listtype, list, elt, c ) \
  105. MACRO_BEGIN \
  106. listtype * *_hook; \
  107. list_find2( elt, list, c, _hook ); \
  108. list_unlink_athook( list, elt, _hook ); \
  109. MACRO_END
  110. /* let elt be the nth element of the list, starting to count from 0.
  111. * Return NULL if out of bounds. */
  112. #define list_nth( elt, list, n ) \
  113. MACRO_BEGIN \
  114. int _x; /* only evaluate n once */ \
  115. for( _x = ( n ), elt = list; _x && elt; _x--, elt = elt->next ) \
  116. { \
  117. } \
  118. MACRO_END
  119. /* let elt be the nth element of the list, starting to count from 0.
  120. * Return NULL if out of bounds. */
  121. #define list_nth_hook( elt, list, n, hook ) \
  122. MACRO_BEGIN \
  123. int _x; /* only evaluate n once */ \
  124. for( _x = ( n ), elt = list, hook = &list; _x && elt; \
  125. _x--, hook = &elt->next, elt = elt->next ) \
  126. { \
  127. } \
  128. MACRO_END
  129. /* set n to the length of the list */
  130. #define list_length( listtype, list, n ) \
  131. MACRO_BEGIN \
  132. listtype * _elt; \
  133. n = 0; \
  134. list_forall( _elt, list ) n++; \
  135. MACRO_END
  136. /* set n to the index of the first element satisfying cond, or -1 if
  137. * none found. Also set elt to the element, or NULL if none found. */
  138. #define list_index( list, n, elt, c ) \
  139. MACRO_BEGIN \
  140. n = 0; \
  141. list_forall( elt, list ) \
  142. { \
  143. if( c ) \
  144. break; \
  145. n++; \
  146. } \
  147. if( !elt ) \
  148. n = -1; \
  149. MACRO_END
  150. /* set n to the number of elements in the list that satisfy condition c */
  151. #define list_count( list, n, elt, c ) \
  152. MACRO_BEGIN \
  153. n = 0; \
  154. list_forall( elt, list ) \
  155. { \
  156. if( c ) \
  157. n++; \
  158. } \
  159. MACRO_END
  160. /* let elt be each element of the list, unlinked. At the end, set list=NULL. */
  161. #define list_forall_unlink( elt, list ) \
  162. for( elt = list; elt ? ( list = elt->next, elt->next = NULL ), 1 : 0; elt = list )
  163. /* reverse a list (efficient) */
  164. #define list_reverse( listtype, list ) \
  165. MACRO_BEGIN \
  166. listtype * _list1 = NULL, *elt; \
  167. list_forall_unlink( elt, list ) list_prepend( _list1, elt ); \
  168. list = _list1; \
  169. MACRO_END
  170. /* insert the element ELT just before the first element TMP of the
  171. * list for which COND holds. Here COND must be a condition of ELT and
  172. * TMP. Typical usage is to insert an element into an ordered list:
  173. * for instance, list_insert_ordered(listtype, list, elt, tmp,
  174. * elt->size <= tmp->size). Note: if we give a "less than or equal"
  175. * condition, the new element will be inserted just before a sequence
  176. * of equal elements. If we give a "less than" condition, the new
  177. * element will be inserted just after a list of equal elements.
  178. * Note: it is much more efficient to construct a list with
  179. * list_prepend and then order it with list_merge_sort, than to
  180. * construct it with list_insert_ordered. */
  181. #define list_insert_ordered( listtype, list, elt, tmp, cond ) \
  182. MACRO_BEGIN \
  183. listtype * *_hook; \
  184. _list_find_hook( list, ( tmp = *_hook, ( cond ) ), _hook ); \
  185. list_insert_athook( elt, _hook ); \
  186. MACRO_END
  187. /* sort the given list, according to the comparison condition.
  188. * Typical usage is list_sort(listtype, list, a, b, a->size <
  189. * b->size). Note: if we give "less than or equal" condition, each
  190. * segment of equal elements will be reversed in order. If we give a
  191. * "less than" condition, each segment of equal elements will retain
  192. * the original order. The latter is slower but sometimes
  193. * prettier. Average running time: n*n/2. */
  194. #define list_sort( listtype, list, a, b, cond ) \
  195. MACRO_BEGIN \
  196. listtype * _newlist = NULL; \
  197. list_forall_unlink( a, list ) list_insert_ordered( listtype, _newlist, a, b, cond ); \
  198. list = _newlist; \
  199. MACRO_END
  200. /* a much faster sort algorithm (merge sort, n log n worst case). It
  201. * is required that the list type has an additional, unused next1
  202. * component. Note there is no curious reversal of order of equal
  203. * elements as for list_sort. */
  204. #define list_mergesort( listtype, list, a, b, cond ) \
  205. MACRO_BEGIN \
  206. listtype * _elt, **_hook1; \
  207. \
  208. for( _elt = list; _elt; _elt = _elt->next1 ) \
  209. { \
  210. _elt->next1 = _elt->next; \
  211. _elt->next = NULL; \
  212. } \
  213. do \
  214. { \
  215. _hook1 = &( list ); \
  216. while( ( a = *_hook1 ) != NULL && ( b = a->next1 ) != NULL ) \
  217. { \
  218. _elt = b->next1; \
  219. _list_merge_cond( listtype, a, b, cond, *_hook1 ); \
  220. _hook1 = &( ( *_hook1 )->next1 ); \
  221. *_hook1 = _elt; \
  222. } \
  223. } \
  224. while( _hook1 != &( list ) ); \
  225. MACRO_END
  226. /* merge two sorted lists. Store result at &result */
  227. #define _list_merge_cond( listtype, a, b, cond, result ) \
  228. MACRO_BEGIN \
  229. listtype * *_hook; \
  230. _hook = &( result ); \
  231. while( 1 ) \
  232. { \
  233. if( a == NULL ) \
  234. { \
  235. *_hook = b; \
  236. break; \
  237. } \
  238. else if( b == NULL ) \
  239. { \
  240. *_hook = a; \
  241. break; \
  242. } \
  243. else if( cond ) \
  244. { \
  245. *_hook = a; \
  246. _hook = &( a->next ); \
  247. a = a->next; \
  248. } \
  249. else \
  250. { \
  251. *_hook = b; \
  252. _hook = &( b->next ); \
  253. b = b->next; \
  254. } \
  255. } \
  256. MACRO_END
  257. /* ---------------------------------------------------------------------- */
  258. /* macros for doubly-linked lists */
  259. #define dlist_append( head, end, elt ) \
  260. MACRO_BEGIN \
  261. elt->prev = end; \
  262. elt->next = NULL; \
  263. if( end ) \
  264. { \
  265. end->next = elt; \
  266. } \
  267. else \
  268. { \
  269. head = elt; \
  270. } \
  271. end = elt; \
  272. MACRO_END
  273. /* let elt be each element of the list, unlinked. At the end, set list=NULL. */
  274. #define dlist_forall_unlink( elt, head, end ) \
  275. for( elt = head; \
  276. elt ? ( head = elt->next, elt->next = NULL, elt->prev = NULL ), 1 : ( end = NULL, 0 ); \
  277. elt = head )
  278. /* unlink the first element of the list */
  279. #define dlist_unlink_first( head, end, elt ) \
  280. MACRO_BEGIN \
  281. elt = head; \
  282. if( head ) \
  283. { \
  284. head = head->next; \
  285. if( head ) \
  286. { \
  287. head->prev = NULL; \
  288. } \
  289. else \
  290. { \
  291. end = NULL; \
  292. } \
  293. elt->prev = NULL; \
  294. elt->next = NULL; \
  295. } \
  296. MACRO_END
  297. #endif /* _PS_LISTS_H */