1 /* PSPP - computes sample statistics.
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 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, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 /* Circular doubly linked lists.
21 This header (llx.h) supplies "external" circular doubly linked
22 lists. Its companion header (ll.h) supplies "embedded"
23 circular doubly linked lists. The two variants are described
24 briefly here. The external variant, for which this is the
25 header, is described in slightly more detail below. Each
26 function also has a detailed usage comment at its point of
29 The "ll" embedded linked list implementation puts the linked
30 list node within the data structure that the list contains.
31 This makes allocation efficient, in space and time. It also
32 makes it easy to find the list node associated with a given
33 object. However, it's difficult to include a given object in
34 an arbitrary number of lists, or to include a single object in
35 a single list in multiple positions.
37 The "llx" external linked list implementation allocates linked
38 list nodes separately from the objects in the list. Adding
39 and removing linked list nodes requires dynamic allocation, so
40 it is normally slower and takes more memory than the embedded
41 implementation. It also requires searching the list to find
42 the list node associated with a given object. However, it's
43 easy to include a given object in an arbitrary number of
44 lists, or to include a single object more than once within a
45 single list. It's also possible to create an external linked
46 list without adding a member to the data structure that the
54 #include <libpspp/ll.h>
56 /* External, circular doubly linked list.
58 Each list contains a single "null" element that separates the
59 head and the tail of the list. The null element is both
60 before the head and after the tail of the list. An empty list
61 contains just the null element.
63 An external linked list is represented as `struct llx_list'.
64 Each node in the list consists of a `struct llx' that contains
65 a `void *' pointer to the node's data. Use the llx_data()
66 function to extract the data pointer from a node.
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 Consider the following declarations:
79 int x; // Data member.
82 Here's an example of iteration from head to tail:
85 for (llx = llx_head (&list); llx != llx_null (&list);
88 struct foo *foo = llx_data (llx);
89 ...do something with foo->x...
92 Here's another way to do it:
94 struct llx *llx = llx_null (&list);
95 while ((llx = llx_next (llx)) != llx_null (&list))
97 struct foo *foo = llx_data (llx);
98 ...do something with foo->x...
102 /* External linked list node. */
105 struct ll ll; /* Node. */
106 void *data; /* Member data. */
112 struct ll_list ll_list; /* The list. */
115 /* Memory manager. */
118 /* Allocates and returns memory for a new struct llx.
119 If space is unavailable, returns a null pointer. */
120 struct llx *(*allocate) (void *aux);
122 /* Releases a previously allocated struct llx. */
123 void (*release) (struct llx *, void *aux);
125 /* Auxiliary data passed to allocate and release
130 /* Manager that uses the standard malloc and free routines. */
131 extern const struct llx_manager llx_malloc_mgr;
133 /* Returns negative if A < B, zero if A == B, positive if A > B. */
134 typedef int llx_compare_func (const void *a, const void *b, void *aux);
136 /* Returns true or false depending on properties of DATA. */
137 typedef bool llx_predicate_func (const void *data, void *aux);
139 /* Takes some action on DATA. */
140 typedef void llx_action_func (void *data, void *aux);
143 static inline void llx_init (struct llx_list *);
144 void llx_destroy (struct llx_list *, llx_action_func *destructor, void *aux,
145 const struct llx_manager *manager);
146 static inline bool llx_is_empty (const struct llx_list *);
147 size_t llx_count (const struct llx_list *);
150 static inline struct llx *llx_head (const struct llx_list *);
151 static inline struct llx *llx_tail (const struct llx_list *);
152 static inline struct llx *llx_null (const struct llx_list *);
153 static inline struct llx *llx_next (const struct llx *);
154 static inline struct llx *llx_prev (const struct llx *);
155 static inline void *llx_data (const struct llx *);
157 /* Stack- and queue-like behavior. */
158 struct llx *llx_push_head (struct llx_list *, void *,
159 const struct llx_manager *);
160 struct llx *llx_push_tail (struct llx_list *, void *,
161 const struct llx_manager *);
162 void *llx_pop_head (struct llx_list *, const struct llx_manager *);
163 void *llx_pop_tail (struct llx_list *, const struct llx_manager *);
166 struct llx *llx_insert (struct llx *before, void *,
167 const struct llx_manager *);
168 void llx_splice (struct llx *before, struct llx *r0, struct llx *r1);
169 void llx_swap (struct llx *a, struct llx *b);
170 void llx_swap_range (struct llx *a0, struct llx *a1,
171 struct llx *b0, struct llx *b1);
174 struct llx *llx_remove (struct llx *, const struct llx_manager *);
175 void llx_remove_range (struct llx *r0, struct llx *r1,
176 const struct llx_manager *);
177 size_t llx_remove_equal (struct llx *r0, struct llx *r1, const void *target,
178 llx_compare_func *, void *aux,
179 const struct llx_manager *);
180 size_t llx_remove_if (struct llx *r0, struct llx *r1,
181 llx_predicate_func *, void *aux,
182 const struct llx_manager *);
184 /* Non-mutating algorithms. */
185 struct llx *llx_find_equal (const struct llx *r0, const struct llx *r1,
187 llx_compare_func *, void *aux);
188 struct llx *llx_find_if (const struct llx *r0, const struct llx *r1,
189 llx_predicate_func *, void *aux);
190 struct llx *llx_find_adjacent_equal (const struct llx *r0,
191 const struct llx *r1,
192 llx_compare_func *, void *aux);
193 size_t llx_count_range (const struct llx *r0, const struct llx *r1);
194 size_t llx_count_equal (const struct llx *r0, const struct llx *r1,
196 llx_compare_func *, void *aux);
197 size_t llx_count_if (const struct llx *r0, const struct llx *r1,
198 llx_predicate_func *, void *aux);
199 struct llx *llx_max (const struct llx *r0, const struct llx *r1,
200 llx_compare_func *, void *aux);
201 struct llx *llx_min (const struct llx *r0, const struct llx *r1,
202 llx_compare_func *, void *aux);
203 int llx_lexicographical_compare_3way (const struct llx *a0,
204 const struct llx *a1,
205 const struct llx *b0,
206 const struct llx *b1,
207 llx_compare_func *, void *aux);
209 /* Mutating algorithms. */
210 void llx_apply (struct llx *r0, struct llx *r1, llx_action_func *, void *aux);
211 void llx_reverse (struct llx *r0, struct llx *r1);
212 bool llx_next_permutation (struct llx *r0, struct llx *r1,
213 llx_compare_func *, void *aux);
214 bool llx_prev_permutation (struct llx *r0, struct llx *r1,
215 llx_compare_func *, void *aux);
217 /* Sorted list functions. */
218 void llx_sort (struct llx *r0, struct llx *r1, llx_compare_func *, void *aux);
219 struct llx *llx_find_run (const struct llx *r0, const struct llx *r1,
220 llx_compare_func *, void *aux);
221 bool llx_is_sorted (const struct llx *r0, const struct llx *r1,
222 llx_compare_func *, void *aux);
223 struct llx *llx_merge (struct llx *a0, struct llx *a1,
224 struct llx *b0, struct llx *b1,
225 llx_compare_func *, void *aux);
226 size_t llx_unique (struct llx *r0, struct llx *r1, struct llx *dups,
227 llx_compare_func *, void *aux,
228 const struct llx_manager *);
229 void llx_sort_unique (struct llx *r0, struct llx *r1, struct llx *dups,
230 llx_compare_func *, void *aux,
231 const struct llx_manager *);
232 struct llx *llx_insert_ordered (struct llx *r0, struct llx *r1, void *data,
233 llx_compare_func *, void *aux,
234 const struct llx_manager *);
235 struct llx *llx_partition (struct llx *r0, struct llx *r1,
236 llx_predicate_func *, void *aux);
237 struct llx *llx_find_partition (const struct llx *r0, const struct llx *r1,
238 llx_predicate_func *, void *aux);
240 /* Returns the llx within which LL is embedded. */
242 llx_from_ll (struct ll *ll)
244 return ll_data (ll, struct llx, ll);
247 /* Initializes LIST as an empty list. */
249 llx_init (struct llx_list *list)
251 ll_init (&list->ll_list);
254 /* Returns true if LIST is empty (contains just the null node),
255 false if LIST is not empty (has at least one other node).
256 Executes in O(1) time. */
258 llx_is_empty (const struct llx_list *list)
260 return ll_is_empty (&list->ll_list);
263 /* Returns the first node in LIST,
264 or the null node if LIST is empty. */
265 static inline struct llx *
266 llx_head (const struct llx_list *list)
268 return llx_from_ll (ll_head (&list->ll_list));
271 /* Returns the last node in LIST,
272 or the null node if LIST is empty. */
273 static inline struct llx *
274 llx_tail (const struct llx_list *list)
276 return llx_from_ll (ll_tail (&list->ll_list));
279 /* Returns LIST's null node. */
280 static inline struct llx *
281 llx_null (const struct llx_list *list)
283 return llx_from_ll (ll_null (&list->ll_list));
286 /* Returns the node following LLX in its list,
287 or the null node if LLX is at the end of its list.
288 (In an empty list, the null node follows itself.) */
289 static inline struct llx *
290 llx_next (const struct llx *llx)
292 return llx_from_ll (ll_next (&llx->ll));
295 /* Returns the node preceding LLX in its list,
296 or the null node if LLX is the first node in its list.
297 (In an empty list, the null node precedes itself.) */
298 static inline struct llx *
299 llx_prev (const struct llx *llx)
301 return llx_from_ll (ll_prev (&llx->ll));
304 /* Returns the data in node LLX. */
306 llx_data (const struct llx *llx)