File indexing completed on 2024-12-22 04:04:12
0001 /* Copyright (C) 2001-2019 Peter Selinger. 0002 This file is part of Potrace. It is free software and it is covered 0003 by the GNU General Public License. See the file COPYING for details. */ 0004 0005 0006 #ifndef _PS_LISTS_H 0007 #define _PS_LISTS_H 0008 0009 /* here we define some general list macros. Because they are macros, 0010 they should work on any datatype with a "->next" component. Some of 0011 them use a "hook". If elt and list are of type t* then hook is of 0012 type t**. A hook stands for an insertion point in the list, i.e., 0013 either before the first element, or between two elements, or after 0014 the last element. If an operation "sets the hook" for an element, 0015 then the hook is set to just before the element. One can insert 0016 something at a hook. One can also unlink at a hook: this means, 0017 unlink the element just after the hook. By "to unlink", we mean the 0018 element is removed from the list, but not deleted. Thus, it and its 0019 components still need to be freed. */ 0020 0021 /* Note: these macros are somewhat experimental. Only the ones that 0022 are actually *used* have been tested. So be careful to test any 0023 that you use. Looking at the output of the preprocessor, "gcc -E" 0024 (possibly piped though "indent"), might help too. Also: these 0025 macros define some internal (local) variables that start with 0026 "_". */ 0027 0028 /* we enclose macro definitions whose body consists of more than one 0029 statement in MACRO_BEGIN and MACRO_END, rather than '{' and '}'. The 0030 reason is that we want to be able to use the macro in a context 0031 such as "if (...) macro(...); else ...". If we didn't use this obscure 0032 trick, we'd have to omit the ";" in such cases. */ 0033 0034 #define MACRO_BEGIN do { 0035 #define MACRO_END } while (0) 0036 0037 /* ---------------------------------------------------------------------- */ 0038 /* macros for singly-linked lists */ 0039 0040 /* traverse list. At the end, elt is set to NULL. */ 0041 #define list_forall(elt, list) for (elt=list; elt!=NULL; elt=elt->next) 0042 0043 /* set elt to the first element of list satisfying boolean condition 0044 c, or NULL if not found */ 0045 #define list_find(elt, list, c) \ 0046 MACRO_BEGIN list_forall(elt, list) if (c) break; MACRO_END 0047 0048 /* like forall, except also set hook for elt. */ 0049 #define list_forall2(elt, list, hook) \ 0050 for (elt=list, hook=&list; elt!=NULL; hook=&elt->next, elt=elt->next) 0051 0052 /* same as list_find, except also set hook for elt. */ 0053 #define list_find2(elt, list, c, hook) \ 0054 MACRO_BEGIN list_forall2(elt, list, hook) if (c) break; MACRO_END 0055 0056 /* same, except only use hook. */ 0057 #define _list_forall_hook(list, hook) \ 0058 for (hook=&list; *hook!=NULL; hook=&(*hook)->next) 0059 0060 /* same, except only use hook. Note: c may only refer to *hook, not elt. */ 0061 #define _list_find_hook(list, c, hook) \ 0062 MACRO_BEGIN _list_forall_hook(list, hook) if (c) break; MACRO_END 0063 0064 /* insert element after hook */ 0065 #define list_insert_athook(elt, hook) \ 0066 MACRO_BEGIN elt->next = *hook; *hook = elt; MACRO_END 0067 0068 /* insert element before hook */ 0069 #define list_insert_beforehook(elt, hook) \ 0070 MACRO_BEGIN elt->next = *hook; *hook = elt; hook=&elt->next; MACRO_END 0071 0072 /* unlink element after hook, let elt be unlinked element, or NULL. 0073 hook remains. */ 0074 #define list_unlink_athook(list, elt, hook) \ 0075 MACRO_BEGIN \ 0076 elt = hook ? *hook : NULL; if (elt) { *hook = elt->next; elt->next = NULL; }\ 0077 MACRO_END 0078 0079 /* unlink the specific element, if it is in the list. Otherwise, set 0080 elt to NULL */ 0081 #define list_unlink(listtype, list, elt) \ 0082 MACRO_BEGIN \ 0083 listtype **_hook; \ 0084 _list_find_hook(list, *_hook==elt, _hook); \ 0085 list_unlink_athook(list, elt, _hook); \ 0086 MACRO_END 0087 0088 /* prepend elt to list */ 0089 #define list_prepend(list, elt) \ 0090 MACRO_BEGIN elt->next = list; list = elt; MACRO_END 0091 0092 /* append elt to list. */ 0093 #define list_append(listtype, list, elt) \ 0094 MACRO_BEGIN \ 0095 listtype **_hook; \ 0096 _list_forall_hook(list, _hook) {} \ 0097 list_insert_athook(elt, _hook); \ 0098 MACRO_END 0099 0100 /* unlink the first element that satisfies the condition. */ 0101 #define list_unlink_cond(listtype, list, elt, c) \ 0102 MACRO_BEGIN \ 0103 listtype **_hook; \ 0104 list_find2(elt, list, c, _hook); \ 0105 list_unlink_athook(list, elt, _hook); \ 0106 MACRO_END 0107 0108 /* let elt be the nth element of the list, starting to count from 0. 0109 Return NULL if out of bounds. */ 0110 #define list_nth(elt, list, n) \ 0111 MACRO_BEGIN \ 0112 int _x; /* only evaluate n once */ \ 0113 for (_x=(n), elt=list; _x && elt; _x--, elt=elt->next) {} \ 0114 MACRO_END 0115 0116 /* let elt be the nth element of the list, starting to count from 0. 0117 Return NULL if out of bounds. */ 0118 #define list_nth_hook(elt, list, n, hook) \ 0119 MACRO_BEGIN \ 0120 int _x; /* only evaluate n once */ \ 0121 for (_x=(n), elt=list, hook=&list; _x && elt; _x--, hook=&elt->next, elt=elt->next) {} \ 0122 MACRO_END 0123 0124 /* set n to the length of the list */ 0125 #define list_length(listtype, list, n) \ 0126 MACRO_BEGIN \ 0127 listtype *_elt; \ 0128 n=0; \ 0129 list_forall(_elt, list) \ 0130 n++; \ 0131 MACRO_END 0132 0133 /* set n to the index of the first element satisfying cond, or -1 if 0134 none found. Also set elt to the element, or NULL if none found. */ 0135 #define list_index(list, n, elt, c) \ 0136 MACRO_BEGIN \ 0137 n=0; \ 0138 list_forall(elt, list) { \ 0139 if (c) break; \ 0140 n++; \ 0141 } \ 0142 if (!elt) \ 0143 n=-1; \ 0144 MACRO_END 0145 0146 /* set n to the number of elements in the list that satisfy condition c */ 0147 #define list_count(list, n, elt, c) \ 0148 MACRO_BEGIN \ 0149 n=0; \ 0150 list_forall(elt, list) { \ 0151 if (c) n++; \ 0152 } \ 0153 MACRO_END 0154 0155 /* let elt be each element of the list, unlinked. At the end, set list=NULL. */ 0156 #define list_forall_unlink(elt, list) \ 0157 for (elt=list; elt ? (list=elt->next, elt->next=NULL), 1 : 0; elt=list) 0158 0159 /* reverse a list (efficient) */ 0160 #define list_reverse(listtype, list) \ 0161 MACRO_BEGIN \ 0162 listtype *_list1=NULL, *elt; \ 0163 list_forall_unlink(elt, list) \ 0164 list_prepend(_list1, elt); \ 0165 list = _list1; \ 0166 MACRO_END 0167 0168 /* insert the element ELT just before the first element TMP of the 0169 list for which COND holds. Here COND must be a condition of ELT and 0170 TMP. Typical usage is to insert an element into an ordered list: 0171 for instance, list_insert_ordered(listtype, list, elt, tmp, 0172 elt->size <= tmp->size). Note: if we give a "less than or equal" 0173 condition, the new element will be inserted just before a sequence 0174 of equal elements. If we give a "less than" condition, the new 0175 element will be inserted just after a list of equal elements. 0176 Note: it is much more efficient to construct a list with 0177 list_prepend and then order it with list_merge_sort, than to 0178 construct it with list_insert_ordered. */ 0179 #define list_insert_ordered(listtype, list, elt, tmp, cond) \ 0180 MACRO_BEGIN \ 0181 listtype **_hook; \ 0182 _list_find_hook(list, (tmp=*_hook, (cond)), _hook); \ 0183 list_insert_athook(elt, _hook); \ 0184 MACRO_END 0185 0186 /* sort the given list, according to the comparison condition. 0187 Typical usage is list_sort(listtype, list, a, b, a->size < 0188 b->size). Note: if we give "less than or equal" condition, each 0189 segment of equal elements will be reversed in order. If we give a 0190 "less than" condition, each segment of equal elements will retain 0191 the original order. The latter is slower but sometimes 0192 prettier. Average running time: n*n/2. */ 0193 #define list_sort(listtype, list, a, b, cond) \ 0194 MACRO_BEGIN \ 0195 listtype *_newlist=NULL; \ 0196 list_forall_unlink(a, list) \ 0197 list_insert_ordered(listtype, _newlist, a, b, cond); \ 0198 list = _newlist; \ 0199 MACRO_END 0200 0201 /* a much faster sort algorithm (merge sort, n log n worst case). It 0202 is required that the list type has an additional, unused next1 0203 component. Note there is no curious reversal of order of equal 0204 elements as for list_sort. */ 0205 0206 #define list_mergesort(listtype, list, a, b, cond) \ 0207 MACRO_BEGIN \ 0208 listtype *_elt, **_hook1; \ 0209 \ 0210 for (_elt=list; _elt; _elt=_elt->next1) { \ 0211 _elt->next1 = _elt->next; \ 0212 _elt->next = NULL; \ 0213 } \ 0214 do { \ 0215 _hook1 = &(list); \ 0216 while ((a = *_hook1) != NULL && (b = a->next1) != NULL ) { \ 0217 _elt = b->next1; \ 0218 _list_merge_cond(listtype, a, b, cond, *_hook1); \ 0219 _hook1 = &((*_hook1)->next1); \ 0220 *_hook1 = _elt; \ 0221 } \ 0222 } while (_hook1 != &(list)); \ 0223 MACRO_END 0224 0225 /* merge two sorted lists. Store result at &result */ 0226 #define _list_merge_cond(listtype, a, b, cond, result) \ 0227 MACRO_BEGIN \ 0228 listtype **_hook; \ 0229 _hook = &(result); \ 0230 while (1) { \ 0231 if (a==NULL) { \ 0232 *_hook = b; \ 0233 break; \ 0234 } else if (b==NULL) { \ 0235 *_hook = a; \ 0236 break; \ 0237 } else if (cond) { \ 0238 *_hook = a; \ 0239 _hook = &(a->next); \ 0240 a = a->next; \ 0241 } else { \ 0242 *_hook = b; \ 0243 _hook = &(b->next); \ 0244 b = b->next; \ 0245 } \ 0246 } \ 0247 MACRO_END 0248 0249 /* ---------------------------------------------------------------------- */ 0250 /* macros for doubly-linked lists */ 0251 0252 #define dlist_append(head, end, elt) \ 0253 MACRO_BEGIN \ 0254 elt->prev = end; \ 0255 elt->next = NULL; \ 0256 if (end) { \ 0257 end->next = elt; \ 0258 } else { \ 0259 head = elt; \ 0260 } \ 0261 end = elt; \ 0262 MACRO_END 0263 0264 /* let elt be each element of the list, unlinked. At the end, set list=NULL. */ 0265 #define dlist_forall_unlink(elt, head, end) \ 0266 for (elt=head; elt ? (head=elt->next, elt->next=NULL, elt->prev=NULL), 1 : (end=NULL, 0); elt=head) 0267 0268 /* unlink the first element of the list */ 0269 #define dlist_unlink_first(head, end, elt) \ 0270 MACRO_BEGIN \ 0271 elt = head; \ 0272 if (head) { \ 0273 head = head->next; \ 0274 if (head) { \ 0275 head->prev = NULL; \ 0276 } else { \ 0277 end = NULL; \ 0278 } \ 0279 elt->prev = NULL; \ 0280 elt->next = NULL; \ 0281 } \ 0282 MACRO_END 0283 0284 #endif /* _PS_LISTS_H */ 0285