xref: /aosp_15_r20/external/toybox/lib/llist.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
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