1 /* void_list.c - the opkg package management system
2 
3    Carl D. Worth
4 
5    Copyright (C) 2001 University of Southern California
6 
7    This program is free software; you can redistribute it and/or
8    modify it under the terms of the GNU General Public License as
9    published by the Free Software Foundation; either version 2, or (at
10    your option) any later version.
11 
12    This program is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    General Public License for more details.
16 */
17 
18 #include "void_list.h"
19 #include "libbb/libbb.h"
20 
void_list_elt_init(void_list_elt_t * elt,void * data)21 void void_list_elt_init(void_list_elt_t * elt, void *data)
22 {
23 	INIT_LIST_HEAD(&elt->node);
24 	elt->data = data;
25 }
26 
void_list_elt_new(void * data)27 static void_list_elt_t *void_list_elt_new(void *data)
28 {
29 	void_list_elt_t *elt;
30 	/* freed in void_list_elt_deinit */
31 	elt = xcalloc(1, sizeof(void_list_elt_t));
32 	void_list_elt_init(elt, data);
33 	return elt;
34 }
35 
void_list_elt_deinit(void_list_elt_t * elt)36 void void_list_elt_deinit(void_list_elt_t * elt)
37 {
38 	list_del_init(&elt->node);
39 	void_list_elt_init(elt, NULL);
40 	free(elt);
41 }
42 
void_list_init(void_list_t * list)43 void void_list_init(void_list_t * list)
44 {
45 	INIT_LIST_HEAD(&list->head);
46 }
47 
void_list_deinit(void_list_t * list)48 void void_list_deinit(void_list_t * list)
49 {
50 	void_list_elt_t *elt;
51 
52 	while (!void_list_empty(list)) {
53 		elt = void_list_pop(list);
54 		void_list_elt_deinit(elt);
55 	}
56 	INIT_LIST_HEAD(&list->head);
57 }
58 
void_list_append(void_list_t * list,void * data)59 void void_list_append(void_list_t * list, void *data)
60 {
61 	void_list_elt_t *elt = void_list_elt_new(data);
62 	list_add_tail(&elt->node, &list->head);
63 }
64 
void_list_push(void_list_t * list,void * data)65 void void_list_push(void_list_t * list, void *data)
66 {
67 	void_list_elt_t *elt = void_list_elt_new(data);
68 	list_add(&elt->node, &list->head);
69 }
70 
void_list_pop(void_list_t * list)71 void_list_elt_t *void_list_pop(void_list_t * list)
72 {
73 	struct list_head *node;
74 
75 	if (void_list_empty(list))
76 		return NULL;
77 	node = list->head.next;
78 	list_del_init(node);
79 	return list_entry(node, void_list_elt_t, node);
80 }
81 
void_list_remove(void_list_t * list,void_list_elt_t ** iter)82 void *void_list_remove(void_list_t * list, void_list_elt_t ** iter)
83 {
84 	void_list_elt_t *pos, *n;
85 	void_list_elt_t *old_elt;
86 	void *old_data = NULL;
87 
88 	old_elt = *iter;
89 	if (!old_elt)
90 		return old_data;
91 	old_data = old_elt->data;
92 
93 	list_for_each_entry_safe(pos, n, &list->head, node) {
94 		if (pos == old_elt)
95 			break;
96 	}
97 	if (pos != old_elt) {
98 		opkg_msg(ERROR, "Internal error: element not found in list.\n");
99 		return NULL;
100 	}
101 
102 	*iter = list_entry(pos->node.prev, void_list_elt_t, node);
103 	void_list_elt_deinit(pos);
104 
105 	return old_data;
106 }
107 
108 /* remove element containing elt data, using cmp(elt->data, target_data) == 0. */
void_list_remove_elt(void_list_t * list,const void * target_data,void_list_cmp_t cmp)109 void *void_list_remove_elt(void_list_t * list, const void *target_data,
110 			   void_list_cmp_t cmp)
111 {
112 	void_list_elt_t *pos, *n;
113 	void *old_data = NULL;
114 	list_for_each_entry_safe(pos, n, &list->head, node) {
115 		if (pos->data && cmp(pos->data, target_data) == 0) {
116 			old_data = pos->data;
117 			void_list_elt_deinit(pos);
118 			break;
119 		}
120 	}
121 	return old_data;
122 }
123 
void_list_first(void_list_t * list)124 void_list_elt_t *void_list_first(void_list_t * list)
125 {
126 	struct list_head *elt;
127 	if (!list)
128 		return NULL;
129 	elt = list->head.next;
130 	if (elt == &list->head) {
131 		return NULL;
132 	}
133 	return list_entry(elt, void_list_elt_t, node);
134 }
135 
void_list_prev(void_list_t * list,void_list_elt_t * node)136 void_list_elt_t *void_list_prev(void_list_t * list, void_list_elt_t * node)
137 {
138 	struct list_head *elt;
139 	if (!list || !node)
140 		return NULL;
141 	elt = node->node.prev;
142 	if (elt == &list->head) {
143 		return NULL;
144 	}
145 	return list_entry(elt, void_list_elt_t, node);
146 }
147 
void_list_next(void_list_t * list,void_list_elt_t * node)148 void_list_elt_t *void_list_next(void_list_t * list, void_list_elt_t * node)
149 {
150 	struct list_head *elt;
151 	if (!list || !node)
152 		return NULL;
153 	elt = node->node.next;
154 	if (elt == &list->head) {
155 		return NULL;
156 	}
157 	return list_entry(elt, void_list_elt_t, node);
158 }
159 
void_list_last(void_list_t * list)160 void_list_elt_t *void_list_last(void_list_t * list)
161 {
162 	struct list_head *elt;
163 	if (!list)
164 		return NULL;
165 	elt = list->head.prev;
166 	if (elt == &list->head) {
167 		return NULL;
168 	}
169 	return list_entry(elt, void_list_elt_t, node);
170 }
171