7 #define CHECK(x) (void)(x)
9 #define CHECK(x) _check(x)
14 list_item *head, *tail;
20 static void _check(const list *l);
21 static list_item * _merge(list_item *, list_item *,
22 comparator *, void *);
23 static list_item * _bisect(list_item *);
24 static list_item * _sort(list_item *,
25 comparator *, void *);
30 list *l = malloc(sizeof *l);
39 l_dtor(list *l, dtor *elt_dtor, void *dtor_aux)
43 l->elt_dtor = elt_dtor;
44 l->dtor_aux = dtor_aux;
55 l_length(const list *l)
57 return l ? l->length : 0;
61 l_is_empty(const list *l)
63 return !l || !l->head;
67 l_first(const list *l)
69 return l ? l->head : NULL;
75 return l ? l->tail : NULL;
79 l_find(const list *l, const void *needle,
80 comparator *cmp, void *aux)
84 for (list_item *li = l_first(l); li; li = li->next)
85 if (cmp(li->data, needle, aux) == 0)
91 l_find_last(const list *l, const void *needle,
92 comparator *cmp, void *aux)
96 for (list_item *li = l_last(l); li; li = li->prev)
97 if (cmp(li->data, needle, aux) == 0)
103 l_append(list *l, void *data)
105 return l_insert_after(l, l_last(l), data);
109 l_prepend(list *l, void *data)
111 return l_insert(l, l_first(l), data);
115 l_remove_first(list *l)
117 list_item *old_head = l_first(l);
118 void *data = old_head ? old_head->data : NULL;
119 l_remove(l, old_head);
124 l_remove_last(list *l)
126 list_item *old_tail = l_last(l);
127 void *data = old_tail ? old_tail->data : NULL;
128 l_remove(l, old_tail);
133 l_remove(list *l, list_item *li)
135 if (!l || !li || l->length < 1)
137 list_item *p = li->prev, *n = li->next;
154 l_insert(list *l, list_item *pos, void *data)
160 list_item *li = malloc(sizeof *li);
164 .prev = pos ? pos->prev : NULL,
171 pos->prev->next = li;
176 l->head = l->tail = li;
177 else if (pos == l->head)
186 l_insert_after(list *l, list_item *pos, void *data)
192 list_item *li = malloc(sizeof *li);
197 .next = pos ? pos->next : NULL,
203 pos->next->prev = li;
208 l->head = l->tail = li;
209 else if (pos == l->tail)
222 list_item *li = l_first(l);
225 list_item *n = li->next;
227 l->elt_dtor(li->data, l->dtor_aux);
231 l->head = l->tail = NULL;
239 l_sort(list *l, comparator *cmp, void *aux)
246 l->head = _sort(l->head, cmp, aux);
247 list_item *t = l->head;
259 _check(const list *l)
262 assert( (!l->head && l->length == 0) ||
263 ( l->head && l->length != 0) );
264 assert( (!l->head && !l->tail) ||
265 ( l->head && l->tail) );
267 /* for extra assurance, could test that the list
268 * is connected front to back and back to front.
270 * Probably adds a good bit of overhead.
271 list_item *li = l_first(l);
272 while (li && li->next)
274 assert(li == l_last(l));
277 while (li && li->prev)
279 assert(li == l_first(l));
284 _merge(list_item *a, list_item *b,
285 comparator *cmp, void *aux)
292 if (cmp(a->data, b->data, aux) <= 0)
295 n = _merge(a->next, b, cmp, aux);
300 n = _merge(a, b->next, cmp, aux);
308 _bisect(list_item *li)
311 list_item *fast = li;
312 while (fast && fast->next)
315 fast = fast->next->next;
317 if (li->prev) /* cut in twain */
318 li->prev = li->prev->next = NULL;
323 _sort(list_item *l, comparator *cmp, void *aux)
329 list_item *r = _bisect(l);
330 l = _sort(l, cmp, aux);
331 r = _sort(r, cmp, aux);
332 return _merge(l, r, cmp, aux);