1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2006, 2009 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 /* Circular doubly linked lists.
19 This header (ll.h) supplies "embedded" circular doubly linked
20 lists. Its companion header (llx.h) supplies "external"
21 circular doubly linked lists. The two variants are described
22 briefly here. The embedded variant, for which this is the
23 header, is described in slightly more detail below. Each
24 function also has a detailed usage comment at its point of
27 The "ll" embedded linked list implementation puts the linked
28 list node within the data structure that the list contains.
29 This makes allocation efficient, in space and time. It also
30 makes it easy to find the list node associated with a given
31 object. However, it's difficult to include a given object in
32 an arbitrary number of lists, or to include a single object in
33 a single list in multiple positions.
35 The "llx" external linked list implementation allocates linked
36 list nodes separately from the objects in the list. Adding
37 and removing linked list nodes requires dynamic allocation, so
38 it is normally slower and takes more memory than the embedded
39 implementation. It also requires searching the list to find
40 the list node associated with a given object. However, it's
41 easy to include a given object in an arbitrary number of
42 lists, or to include a single object more than once within a
43 single list. It's also possible to create an external linked
44 list without adding a member to the data structure that the
53 #include <libpspp/cast.h>
55 #include <libpspp/cast.h>
57 /* Embedded, circular doubly linked list.
59 Each list contains a single "null" element that separates the
60 head and the tail of the list. The null element is both
61 before the head and after the tail of the list. An empty list
62 contains just the null element.
64 An embedded linked list is represented as `struct ll_list'.
65 Each node in the list, presumably a structure type, must
66 include a `struct ll' member.
68 Many list functions take ranges of nodes as arguments. Ranges
69 are "half-open"; that is, R0...R1 includes R0 but not R1. A
70 range whose endpoints are the same (e.g. R0...R0) contains no
73 Here's an example of a structure type that includes a `struct
80 struct ll ll; // List member.
81 int x; // Another member.
84 Here's an example of iteration from head to tail:
87 for (ll = ll_head (&list); ll != ll_null (&list); ll = ll_next (ll))
89 struct foo *foo = ll_data (ll, struct foo, ll);
90 ...do something with foo->x...
93 Here's another way to do it:
95 struct ll *ll = ll_null (&list);
96 while ((ll = ll_next (ll)) != ll_null (&list))
98 struct foo *foo = ll_data (ll, struct foo, ll);
99 ...do something with foo->x...
105 ll_for_each (foo, struct foo, ll, &list)
107 ...do something with foo->x...
111 /* Returns the data structure corresponding to the given node LL,
112 assuming that LL is embedded as the given MEMBER name in data
114 #define ll_data(LL, STRUCT, MEMBER) \
115 (CHECK_POINTER_HAS_TYPE(LL, struct ll *), \
116 UP_CAST(LL, STRUCT, MEMBER))
118 /* Linked list node. */
121 struct ll *next; /* Next node. */
122 struct ll *prev; /* Previous node. */
128 struct ll null; /* Null node. */
131 /* Returns negative if A < B, zero if A == B, positive if A > B. */
132 typedef int ll_compare_func (const struct ll *a,
133 const struct ll *b, void *aux);
135 /* Returns true or false depending on properties of LL. */
136 typedef bool ll_predicate_func (const struct ll *ll, void *aux);
138 /* Takes some action on LL. */
139 typedef void ll_action_func (struct ll *ll, void *aux);
141 /* Suitable for use as the initializer for a `struct ll_list'
142 named LIST. Typical usage:
143 struct ll_list list = LL_INITIALIZER (list);
144 LL_INITIALIZER() is an alternative to ll_init(). */
145 #define LL_INITIALIZER(LIST) { { &(LIST).null, &(LIST).null } }
148 static inline void ll_init (struct ll_list *);
149 static inline bool ll_is_empty (const struct ll_list *);
150 size_t ll_count (const struct ll_list *);
153 static inline struct ll *ll_head (const struct ll_list *);
154 static inline struct ll *ll_tail (const struct ll_list *);
155 static inline struct ll *ll_null (const struct ll_list *);
156 static inline struct ll *ll_next (const struct ll *);
157 static inline struct ll *ll_prev (const struct ll *);
159 /* Stack- and queue-like behavior. */
160 static inline void ll_push_head (struct ll_list *, struct ll *);
161 static inline void ll_push_tail (struct ll_list *, struct ll *);
162 static inline struct ll *ll_pop_head (struct ll_list *);
163 static inline struct ll *ll_pop_tail (struct ll_list *);
166 static inline void ll_insert (struct ll *before, struct ll *new);
167 void ll_splice (struct ll *before, struct ll *r0, struct ll *r1);
168 void ll_swap (struct ll *a, struct ll *b);
169 void ll_swap_range (struct ll *a0, struct ll *a1,
170 struct ll *b0, struct ll *b1);
173 static inline struct ll *ll_remove (struct ll *);
174 static inline void ll_remove_range (struct ll *r0, struct ll *r1);
175 size_t ll_remove_equal (struct ll *r0, struct ll *r1, struct ll *target,
176 ll_compare_func *, void *aux);
177 size_t ll_remove_if (struct ll *r0, struct ll *r1,
178 ll_predicate_func *, void *aux);
179 static inline void ll_moved (struct ll *);
181 /* Non-mutating algorithms. */
182 struct ll *ll_find_equal (const struct ll *r0, const struct ll *r1,
183 const struct ll *target,
184 ll_compare_func *, void *aux);
185 struct ll *ll_find_if (const struct ll *r0, const struct ll *r1,
186 ll_predicate_func *, void *aux);
187 struct ll *ll_find_adjacent_equal (const struct ll *r0, const struct ll *r1,
188 ll_compare_func *, void *aux);
189 size_t ll_count_range (const struct ll *r0, const struct ll *r1);
190 size_t ll_count_equal (const struct ll *r0, const struct ll *r1,
191 const struct ll *target,
192 ll_compare_func *, void *aux);
193 size_t ll_count_if (const struct ll *r0, const struct ll *r1,
194 ll_predicate_func *, void *aux);
195 struct ll *ll_max (const struct ll *r0, const struct ll *r1,
196 ll_compare_func *, void *aux);
197 struct ll *ll_min (const struct ll *r0, const struct ll *r1,
198 ll_compare_func *, void *aux);
199 int ll_lexicographical_compare_3way (const struct ll *a0, const struct ll *a1,
200 const struct ll *b0, const struct ll *b1,
201 ll_compare_func *, void *aux);
203 /* Mutating algorithms. */
204 void ll_apply (struct ll *r0, struct ll *r1, ll_action_func *, void *aux);
205 void ll_reverse (struct ll *r0, struct ll *r1);
206 bool ll_next_permutation (struct ll *r0, struct ll *r1,
207 ll_compare_func *, void *aux);
208 bool ll_prev_permutation (struct ll *r0, struct ll *r1,
209 ll_compare_func *, void *aux);
211 /* Sorted list functions. */
212 void ll_sort (struct ll *r0, struct ll *r1, ll_compare_func *, void *aux);
213 struct ll *ll_find_run (const struct ll *r0, const struct ll *r1,
214 ll_compare_func *, void *aux);
215 struct ll *ll_merge (struct ll *a0, struct ll *a1,
216 struct ll *b0, struct ll *b1,
217 ll_compare_func *, void *aux);
218 bool ll_is_sorted (const struct ll *r0, const struct ll *r1,
219 ll_compare_func *, void *aux);
220 size_t ll_unique (struct ll *r0, struct ll *r1, struct ll *dups,
221 ll_compare_func *, void *aux);
222 void ll_sort_unique (struct ll *r0, struct ll *r1, struct ll *dups,
223 ll_compare_func *, void *aux);
224 void ll_insert_ordered (struct ll *r0, struct ll *r1, struct ll *new_elem,
225 ll_compare_func *, void *aux);
226 struct ll *ll_partition (struct ll *r0, struct ll *r1,
227 ll_predicate_func *, void *aux);
228 struct ll *ll_find_partition (const struct ll *r0, const struct ll *r1,
229 ll_predicate_func *, void *aux);
231 /* Iteration helper macros. */
233 /* Sets DATA to each object in LIST in turn, in forward or
234 reverse order, assuming that each
235 `struct ll' in LIST is embedded as the given MEMBER name in
238 Behavior is undefined if DATA is removed from the list between
240 #define ll_for_each(DATA, STRUCT, MEMBER, LIST) \
241 for (DATA = ll_head__ (STRUCT, MEMBER, LIST); \
243 DATA = ll_next__ (DATA, STRUCT, MEMBER, LIST))
244 #define ll_for_each_reverse(DATA, STRUCT, MEMBER, LIST) \
245 for (DATA = ll_tail__ (STRUCT, MEMBER, LIST); \
247 DATA = ll_prev__ (DATA, STRUCT, MEMBER, LIST))
249 /* Continues a iteration of LIST, starting from the object
250 currently in DATA and continuing, in forward or reverse order,
251 through the remainder of the list, assuming that each `struct
252 ll' in LIST is embedded as the given MEMBER name in data type
255 Behavior is undefined if DATA is removed from the list between
257 #define ll_for_each_continue(DATA, STRUCT, MEMBER, LIST) \
260 DATA = ll_next__ (DATA, STRUCT, MEMBER, LIST))
261 #define ll_for_each_reverse_continue(DATA, STRUCT, MEMBER, LIST) \
264 DATA = ll_prev__ (DATA, STRUCT, MEMBER, LIST))
266 /* Sets DATA to each object in LIST in turn, in forward or
267 reverse order, assuming that each `struct ll' in LIST is
268 embedded as the given MEMBER name in data type STRUCT. NEXT
269 (or PREV) must be another variable of the same type as DATA.
271 Behavior is well-defined even if DATA is removed from the list
272 between iterations. */
273 #define ll_for_each_safe(DATA, NEXT, STRUCT, MEMBER, LIST) \
274 for (DATA = ll_head__ (STRUCT, MEMBER, LIST); \
276 ? (NEXT = ll_next__ (DATA, STRUCT, MEMBER, LIST), 1) \
279 #define ll_for_each_reverse_safe(DATA, PREV, STRUCT, MEMBER, LIST) \
280 for (DATA = ll_tail__ (STRUCT, MEMBER, LIST); \
282 ? (PREV = ll_prev__ (DATA, STRUCT, MEMBER, LIST), 1) \
286 /* Continues a iteration of LIST, in forward or reverse order,
287 starting from the object currently in DATA and continuing
288 forward through the remainder of the list, assuming that each
289 `struct ll' in LIST is embedded as the given MEMBER name in
290 data type STRUCT. NEXT (or PREV) must be another variable of
291 the same type as DATA.
293 Behavior is well-defined even if DATA is removed from the list
294 between iterations. */
295 #define ll_for_each_safe_continue(DATA, NEXT, STRUCT, MEMBER, LIST) \
298 ? (NEXT = ll_next__ (DATA, STRUCT, MEMBER, LIST), 1) \
301 #define ll_for_each_safe_reverse_continue(DATA, PREV, STRUCT, MEMBER, LIST) \
304 ? (PREV = ll_prev__ (DATA, STRUCT, MEMBER, LIST), 1) \
308 /* Sets DATA to each object in LIST in turn, in forward or
309 reverse order, assuming that each `struct ll' in LIST is
310 embedded as the given MEMBER name in data type STRUCT.
311 Each object is removed from LIST before its loop iteration. */
312 #define ll_for_each_preremove(DATA, STRUCT, MEMBER, LIST) \
313 while (!ll_is_empty (LIST) \
314 ? (DATA = ll_data (ll_pop_head (LIST), STRUCT, MEMBER), 1) \
316 #define ll_for_each_reverse_preremove(DATA, STRUCT, MEMBER, LIST) \
317 while (!ll_is_empty (LIST) \
318 ? (DATA = ll_data (ll_pop_tail (LIST), STRUCT, MEMBER), 1) \
321 /* Sets DATA to each object in LIST in turn, in forward or
322 reverse order, assuming that each `struct ll' in LIST is
323 embedded as the given MEMBER name in data type STRUCT.
324 At the end of each loop iteration, DATA is removed from the
326 #define ll_for_each_postremove(DATA, STRUCT, MEMBER, LIST) \
328 (DATA = ll_head__ (STRUCT, MEMBER, LIST)) != NULL; \
329 ll_remove (&DATA->MEMBER))
330 #define ll_for_each_reverse_postremove(DATA, STRUCT, MEMBER, LIST) \
332 (DATA = ll_tail__ (STRUCT, MEMBER, LIST)) != NULL; \
333 ll_remove (&DATA->MEMBER))
335 /* Macros for internal use only. */
336 #define ll_data__(LL, STRUCT, MEMBER, LIST) \
337 ((LL) != ll_null (LIST) ? ll_data (LL, STRUCT, MEMBER) : NULL)
338 #define ll_head__(STRUCT, MEMBER, LIST) \
339 ll_data__ (ll_head (LIST), STRUCT, MEMBER, LIST)
340 #define ll_tail__(STRUCT, MEMBER, LIST) \
341 ll_data__ (ll_tail (LIST), STRUCT, MEMBER, LIST)
342 #define ll_next__(DATA, STRUCT, MEMBER, LIST) \
343 ll_data__ (ll_next (&(DATA)->MEMBER), STRUCT, MEMBER, LIST)
344 #define ll_prev__(DATA, STRUCT, MEMBER, LIST) \
345 ll_data__ (ll_prev (&(DATA)->MEMBER), STRUCT, MEMBER, LIST)
347 /* Inline functions. */
349 /* Initializes LIST as an empty list. */
351 ll_init (struct ll_list *list)
353 list->null.next = list->null.prev = &list->null;
356 /* Returns true if LIST is empty (contains just the null node),
357 false if LIST is not empty (has at least one other node).
358 Executes in O(1) time. */
360 ll_is_empty (const struct ll_list *list)
362 return ll_head (list) == ll_null (list);
365 /* Returns the first node in LIST,
366 or the null node if LIST is empty. */
367 static inline struct ll *
368 ll_head (const struct ll_list *list)
370 return ll_next (ll_null (list));
373 /* Returns the last node in LIST,
374 or the null node if LIST is empty. */
375 static inline struct ll *
376 ll_tail (const struct ll_list *list)
378 return ll_prev (ll_null (list));
381 /* Returns LIST's null node. */
382 static inline struct ll *
383 ll_null (const struct ll_list *list)
385 return CONST_CAST (struct ll *, &list->null);
388 /* Returns the node following LL in its list,
389 or the null node if LL is at the end of its list.
390 (In an empty list, the null node follows itself.) */
391 static inline struct ll *
392 ll_next (const struct ll *ll)
397 /* Returns the node preceding LL in its list,
398 or the null node if LL is the first node in its list.
399 (In an empty list, the null node precedes itself.) */
400 static inline struct ll *
401 ll_prev (const struct ll *ll)
406 /* Inserts LL at the head of LIST. */
408 ll_push_head (struct ll_list *list, struct ll *ll)
410 ll_insert (ll_head (list), ll);
413 /* Inserts LL at the tail of LIST. */
415 ll_push_tail (struct ll_list *list, struct ll *ll)
417 ll_insert (ll_null (list), ll);
420 /* Removes and returns the first node in LIST,
421 which must not be empty. */
422 static inline struct ll *
423 ll_pop_head (struct ll_list *list)
426 assert (!ll_is_empty (list));
427 head = ll_head (list);
432 /* Removes and returns the last node in LIST,
433 which must not be empty. */
434 static inline struct ll *
435 ll_pop_tail (struct ll_list *list)
438 assert (!ll_is_empty (list));
439 tail = ll_tail (list);
444 /* Inserts NEW_ELEM just before BEFORE.
445 (NEW_ELEM must not already be in a list.) */
447 ll_insert (struct ll *before, struct ll *new_elem)
449 struct ll *before_prev = ll_prev (before);
450 new_elem->next = before;
451 new_elem->prev = before_prev;
452 before_prev->next = before->prev = new_elem;
455 /* Removes LL from its list
456 and returns the node that formerly followed it. */
457 static inline struct ll *
458 ll_remove (struct ll *ll)
460 struct ll *next = ll_next (ll);
461 ll->prev->next = next;
462 ll->next->prev = ll->prev;
466 /* Removes R0...R1 from their list. */
468 ll_remove_range (struct ll *r0, struct ll *r1)
473 r0->prev->next = r1->next;
474 r1->next->prev = r0->prev;
478 /* Adjusts the nodes around LL to compensate for LL having
479 changed address, e.g. due to LL being inside a block of memory
480 that was realloc()'d. Equivalent to calling ll_remove()
481 before moving LL, then ll_insert() afterward, but more
484 ll_moved (struct ll *ll)
486 ll->prev->next = ll->next->prev = ll;