1*cf5a6c84SAndroid Build Coastguard Worker /* llist.c - Linked list functions
2*cf5a6c84SAndroid Build Coastguard Worker *
3*cf5a6c84SAndroid Build Coastguard Worker * Linked list structures have a next pointer as their first element.
4*cf5a6c84SAndroid Build Coastguard Worker */
5*cf5a6c84SAndroid Build Coastguard Worker
6*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
7*cf5a6c84SAndroid Build Coastguard Worker
8*cf5a6c84SAndroid Build Coastguard Worker // Callback function to free data pointer of double_list or arg_list
9*cf5a6c84SAndroid Build Coastguard Worker
llist_free_arg(void * node)10*cf5a6c84SAndroid Build Coastguard Worker void llist_free_arg(void *node)
11*cf5a6c84SAndroid Build Coastguard Worker {
12*cf5a6c84SAndroid Build Coastguard Worker struct arg_list *d = node;
13*cf5a6c84SAndroid Build Coastguard Worker
14*cf5a6c84SAndroid Build Coastguard Worker free(d->arg);
15*cf5a6c84SAndroid Build Coastguard Worker free(d);
16*cf5a6c84SAndroid Build Coastguard Worker }
17*cf5a6c84SAndroid Build Coastguard Worker
llist_free_double(void * node)18*cf5a6c84SAndroid Build Coastguard Worker void llist_free_double(void *node)
19*cf5a6c84SAndroid Build Coastguard Worker {
20*cf5a6c84SAndroid Build Coastguard Worker struct double_list *d = node;
21*cf5a6c84SAndroid Build Coastguard Worker
22*cf5a6c84SAndroid Build Coastguard Worker free(d->data);
23*cf5a6c84SAndroid Build Coastguard Worker free(d);
24*cf5a6c84SAndroid Build Coastguard Worker }
25*cf5a6c84SAndroid Build Coastguard Worker
26*cf5a6c84SAndroid Build Coastguard Worker // Call a function (such as free()) on each element of a linked list.
llist_traverse(void * list,void (* using)(void * node))27*cf5a6c84SAndroid Build Coastguard Worker void llist_traverse(void *list, void (*using)(void *node))
28*cf5a6c84SAndroid Build Coastguard Worker {
29*cf5a6c84SAndroid Build Coastguard Worker void *old = list;
30*cf5a6c84SAndroid Build Coastguard Worker
31*cf5a6c84SAndroid Build Coastguard Worker while (list) {
32*cf5a6c84SAndroid Build Coastguard Worker void *pop = llist_pop(&list);
33*cf5a6c84SAndroid Build Coastguard Worker using(pop);
34*cf5a6c84SAndroid Build Coastguard Worker
35*cf5a6c84SAndroid Build Coastguard Worker // End doubly linked list too.
36*cf5a6c84SAndroid Build Coastguard Worker if (old == list) break;
37*cf5a6c84SAndroid Build Coastguard Worker }
38*cf5a6c84SAndroid Build Coastguard Worker }
39*cf5a6c84SAndroid Build Coastguard Worker
40*cf5a6c84SAndroid Build Coastguard Worker // Return the first item from the list, advancing the list (which must be called
41*cf5a6c84SAndroid Build Coastguard Worker // as &list)
llist_pop(void * list)42*cf5a6c84SAndroid Build Coastguard Worker void *llist_pop(void *list)
43*cf5a6c84SAndroid Build Coastguard Worker {
44*cf5a6c84SAndroid Build Coastguard Worker void **llist = list, **next;
45*cf5a6c84SAndroid Build Coastguard Worker
46*cf5a6c84SAndroid Build Coastguard Worker if (!list || !*llist) return 0;
47*cf5a6c84SAndroid Build Coastguard Worker next = (void **)*llist;
48*cf5a6c84SAndroid Build Coastguard Worker *llist = *next;
49*cf5a6c84SAndroid Build Coastguard Worker
50*cf5a6c84SAndroid Build Coastguard Worker return next;
51*cf5a6c84SAndroid Build Coastguard Worker }
52*cf5a6c84SAndroid Build Coastguard Worker
53*cf5a6c84SAndroid Build Coastguard Worker // Remove first item from &list and return it
dlist_pop(void * list)54*cf5a6c84SAndroid Build Coastguard Worker void *dlist_pop(void *list)
55*cf5a6c84SAndroid Build Coastguard Worker {
56*cf5a6c84SAndroid Build Coastguard Worker struct double_list **pdlist = (struct double_list **)list, *dlist = *pdlist;
57*cf5a6c84SAndroid Build Coastguard Worker
58*cf5a6c84SAndroid Build Coastguard Worker if (!dlist) return 0;
59*cf5a6c84SAndroid Build Coastguard Worker if (dlist->next == dlist) *pdlist = 0;
60*cf5a6c84SAndroid Build Coastguard Worker else {
61*cf5a6c84SAndroid Build Coastguard Worker if (dlist->next) dlist->next->prev = dlist->prev;
62*cf5a6c84SAndroid Build Coastguard Worker if (dlist->prev) dlist->prev->next = dlist->next;
63*cf5a6c84SAndroid Build Coastguard Worker *pdlist = dlist->next;
64*cf5a6c84SAndroid Build Coastguard Worker }
65*cf5a6c84SAndroid Build Coastguard Worker
66*cf5a6c84SAndroid Build Coastguard Worker return dlist;
67*cf5a6c84SAndroid Build Coastguard Worker }
68*cf5a6c84SAndroid Build Coastguard Worker
69*cf5a6c84SAndroid Build Coastguard Worker // remove last item from &list and return it (stack pop)
dlist_lpop(void * list)70*cf5a6c84SAndroid Build Coastguard Worker void *dlist_lpop(void *list)
71*cf5a6c84SAndroid Build Coastguard Worker {
72*cf5a6c84SAndroid Build Coastguard Worker struct double_list *dl = *(struct double_list **)list;
73*cf5a6c84SAndroid Build Coastguard Worker void *v = 0;
74*cf5a6c84SAndroid Build Coastguard Worker
75*cf5a6c84SAndroid Build Coastguard Worker if (dl) {
76*cf5a6c84SAndroid Build Coastguard Worker dl = dl->prev;
77*cf5a6c84SAndroid Build Coastguard Worker v = dlist_pop(&dl);
78*cf5a6c84SAndroid Build Coastguard Worker if (!dl) *(void **)list = 0;
79*cf5a6c84SAndroid Build Coastguard Worker }
80*cf5a6c84SAndroid Build Coastguard Worker
81*cf5a6c84SAndroid Build Coastguard Worker return v;
82*cf5a6c84SAndroid Build Coastguard Worker }
83*cf5a6c84SAndroid Build Coastguard Worker
84*cf5a6c84SAndroid Build Coastguard Worker // Append to list in-order (*list unchanged unless empty, ->prev is new node)
dlist_add_nomalloc(struct double_list ** list,struct double_list * new)85*cf5a6c84SAndroid Build Coastguard Worker void dlist_add_nomalloc(struct double_list **list, struct double_list *new)
86*cf5a6c84SAndroid Build Coastguard Worker {
87*cf5a6c84SAndroid Build Coastguard Worker if (*list) {
88*cf5a6c84SAndroid Build Coastguard Worker new->next = *list;
89*cf5a6c84SAndroid Build Coastguard Worker new->prev = (*list)->prev;
90*cf5a6c84SAndroid Build Coastguard Worker (*list)->prev->next = new;
91*cf5a6c84SAndroid Build Coastguard Worker (*list)->prev = new;
92*cf5a6c84SAndroid Build Coastguard Worker } else *list = new->next = new->prev = new;
93*cf5a6c84SAndroid Build Coastguard Worker }
94*cf5a6c84SAndroid Build Coastguard Worker
95*cf5a6c84SAndroid Build Coastguard Worker // Add an entry to the end of a doubly linked list
dlist_add(struct double_list ** list,char * data)96*cf5a6c84SAndroid Build Coastguard Worker struct double_list *dlist_add(struct double_list **list, char *data)
97*cf5a6c84SAndroid Build Coastguard Worker {
98*cf5a6c84SAndroid Build Coastguard Worker struct double_list *new = xmalloc(sizeof(struct double_list));
99*cf5a6c84SAndroid Build Coastguard Worker
100*cf5a6c84SAndroid Build Coastguard Worker new->data = data;
101*cf5a6c84SAndroid Build Coastguard Worker dlist_add_nomalloc(list, new);
102*cf5a6c84SAndroid Build Coastguard Worker
103*cf5a6c84SAndroid Build Coastguard Worker return new;
104*cf5a6c84SAndroid Build Coastguard Worker }
105*cf5a6c84SAndroid Build Coastguard Worker
106*cf5a6c84SAndroid Build Coastguard Worker // Terminate circular list for traversal in either direction. Returns end *.
dlist_terminate(void * list)107*cf5a6c84SAndroid Build Coastguard Worker void *dlist_terminate(void *list)
108*cf5a6c84SAndroid Build Coastguard Worker {
109*cf5a6c84SAndroid Build Coastguard Worker struct double_list *end = list;
110*cf5a6c84SAndroid Build Coastguard Worker
111*cf5a6c84SAndroid Build Coastguard Worker if (!end || !end->prev) return 0;
112*cf5a6c84SAndroid Build Coastguard Worker
113*cf5a6c84SAndroid Build Coastguard Worker end = end->prev;
114*cf5a6c84SAndroid Build Coastguard Worker end->next->prev = 0;
115*cf5a6c84SAndroid Build Coastguard Worker end->next = 0;
116*cf5a6c84SAndroid Build Coastguard Worker
117*cf5a6c84SAndroid Build Coastguard Worker return end;
118*cf5a6c84SAndroid Build Coastguard Worker }
119