1 /* libcomps - C alternative to yum.comps library
2 * Copyright (C) 2013 Jindrich Luza
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * any later version.
8 *
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
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17 * USA
18 */
19
20 #include "comps_hslist.h"
21 #include "comps_set.h"
22
23 #include <stdlib.h>
comps_hslist_create()24 COMPS_HSList * comps_hslist_create() {
25 COMPS_HSList *ret;
26 ret = malloc(sizeof(COMPS_HSList));
27 if (!ret) {
28 return NULL;
29 }
30 return ret;
31 }
32
comps_hslist_init(COMPS_HSList * hslist,void * (* data_constructor)(void * data),void * (* data_cloner)(void * data),void (* data_destructor)(void * data))33 void comps_hslist_init(COMPS_HSList * hslist,
34 void*(*data_constructor)(void* data),
35 void*(*data_cloner)(void* data),
36 void(*data_destructor)(void* data)) {
37 if (hslist == NULL) {
38 return;
39 }
40 hslist->data_constructor = data_constructor;
41 hslist->data_destructor = data_destructor;
42 hslist->data_cloner = data_cloner;
43 hslist->first = NULL;
44 hslist->last = NULL;
45 }
46
comps_hslist_append(COMPS_HSList * hslist,void * data,unsigned construct)47 void comps_hslist_append(COMPS_HSList * hslist, void * data, unsigned construct) {
48 COMPS_HSListItem * it;
49
50 if (hslist == NULL)
51 return;
52 if ((it = malloc(sizeof(*it))) == NULL)
53 return;
54 if (construct && hslist->data_constructor) {
55 it->data = hslist->data_constructor(data);
56 } else {
57 it->data = data;
58 }
59 it->next = NULL;
60 if (hslist->last == NULL) {
61 hslist->last = it;
62 hslist->first = it;
63 } else {
64 hslist->last->next = it;
65 hslist->last = hslist->last->next;
66 }
67 }
68
comps_hslist_insert_after(COMPS_HSList * hslist,COMPS_HSListItem * item,void * data,unsigned construct)69 void comps_hslist_insert_after(COMPS_HSList * hslist, COMPS_HSListItem *item,
70 void *data, unsigned construct) {
71 COMPS_HSListItem * it;
72 void * ndata;
73
74 if (hslist == NULL || item == NULL)
75 return;
76 if ((it = malloc(sizeof(*it))) == NULL)
77 return;
78 if (construct && hslist->data_constructor) {
79 ndata = hslist->data_constructor(data);
80 } else {
81 ndata = data;
82 }
83 it->data = ndata;
84 it->next = item->next;
85 item->next = it;
86 if (item == hslist->last) {
87 //printf("inserting after last\n");
88 hslist->last = it;
89 }
90 }
comps_hslist_insert_at(COMPS_HSList * hslist,int pos,void * data,unsigned construct)91 int comps_hslist_insert_at(COMPS_HSList * hslist, int pos,
92 void *data, unsigned construct) {
93 COMPS_HSListItem *it, *oldit, *newit;
94 int n;
95
96 if (hslist == NULL)
97 return 0;
98 if ((newit = malloc(sizeof(*newit))) == NULL)
99 return 0;
100 if (construct && hslist->data_constructor) {
101 newit->data = hslist->data_constructor(data);
102 } else {
103 newit->data = data;
104 }
105 oldit=NULL;
106 for (n=0, it = hslist->first; n != pos && it != NULL; n++, it = it->next) {
107 oldit = it;
108 }
109 if (n == 0 && pos == 0) {
110 newit->next = hslist->first;
111 hslist->first = newit;
112 if (hslist->last == NULL)
113 hslist->last = newit;
114 } else if (n == pos) {
115 newit->next = oldit->next;
116 oldit->next = newit;
117 } else {
118 if (hslist->data_destructor)
119 hslist->data_destructor(newit->data);
120 free(newit);
121 }
122 return 1;
123 }
124
comps_hslist_prepend(COMPS_HSList * hslist,void * data,unsigned construct)125 void comps_hslist_prepend(COMPS_HSList * hslist, void *data, unsigned construct) {
126 COMPS_HSListItem * it;
127 void * ndata;
128
129 if (hslist == NULL)
130 return;
131 if ((it = malloc(sizeof(*it))) == NULL)
132 return;
133 if (construct && hslist->data_constructor) {
134 ndata = hslist->data_constructor(data);
135 } else {
136 ndata = data;
137 }
138 it->data = ndata;
139 it->next = hslist->first;
140 hslist->first = it;
141 }
142
comps_hslist_shift(COMPS_HSList * hslist)143 void* comps_hslist_shift(COMPS_HSList * hslist) {
144 void * data;
145 COMPS_HSListItem *it;
146
147 if (hslist == NULL || hslist->first == NULL) {
148 //printf("ret null %p\n", hslist->first);
149 return NULL;
150 }
151 it = hslist->first;
152 data = hslist->first->data;
153 hslist->first = hslist->first->next;
154 if (hslist->first == NULL)
155 hslist->last=NULL;
156 free(it);
157 return data;
158 }
159
comps_hslist_pop(COMPS_HSList * hslist)160 void* comps_hslist_pop(COMPS_HSList * hslist) {
161 void * data;
162 COMPS_HSListItem *it, *it2;
163
164 if (hslist == NULL || hslist->first == NULL)
165 return NULL;
166 it2 = NULL;
167 for (it = hslist->first; it != hslist->last; it2=it, it = it->next);
168
169 if (!it2) {
170 hslist->last = NULL;
171 hslist->first = NULL;
172 } else {
173 hslist->last = it2;
174 it2->next = NULL;
175 }
176 data = it->data;
177 free(it);
178 return data;
179 }
180
comps_hslist_destroy_v(void ** hslist)181 inline void comps_hslist_destroy_v(void ** hslist) {
182 comps_hslist_destroy((COMPS_HSList**) hslist);
183 }
184
comps_hslist_destroy(COMPS_HSList ** hslist)185 void comps_hslist_destroy(COMPS_HSList ** hslist) {
186 COMPS_HSListItem *it,*oldit;
187 unsigned int x;
188 if (*hslist == NULL) return;
189 oldit = (*hslist)->first;
190 it = (oldit)?oldit->next:NULL;
191 for (x=0 ;it != NULL; it=it->next, x++) {
192 if ((*hslist)->data_destructor != NULL)
193 (*hslist)->data_destructor(oldit->data);
194 free(oldit);
195 oldit = it;
196 }
197 if (oldit) {
198 if ((*hslist)->data_destructor != NULL)
199 (*hslist)->data_destructor(oldit->data);
200 free(oldit);
201 }
202 free(*hslist);
203 *hslist = NULL;
204 }
205
comps_hslist_remove(COMPS_HSList * hslist,COMPS_HSListItem * it)206 void comps_hslist_remove(COMPS_HSList * hslist,
207 COMPS_HSListItem * it) {
208 COMPS_HSListItem *itx, *itprev=NULL;
209 if (it == NULL) return;
210 for (itx = hslist->first; itx != NULL && itx != it; itx = itx->next) {
211 itprev = itx;
212 }
213 if (itx != it)
214 return;
215 if (itprev == NULL) {
216 if (hslist->first == hslist->last)
217 hslist->last = hslist->first->next;
218 hslist->first = hslist->first->next;
219 } else {
220 itprev->next = it->next;
221 if (it == hslist->last) {
222 if (hslist->first == hslist->last)
223 hslist->first = itprev;
224 hslist->last = itprev;
225 }
226 }
227 }
228
comps_hslist_data_at(COMPS_HSList * hlist,unsigned int index)229 void* comps_hslist_data_at(COMPS_HSList * hlist, unsigned int index)
230 {
231 unsigned int i=0;
232 COMPS_HSListItem * itx;
233 for (itx = hlist->first; itx != NULL && index != i; itx = itx->next, i++);
234 if (itx == NULL)
235 return itx;
236 else
237 return itx->data;
238 }
239
comps_hslist_clone(COMPS_HSList * hslist)240 COMPS_HSList* comps_hslist_clone(COMPS_HSList * hslist) {
241 COMPS_HSList *ret;
242 COMPS_HSListItem *it;
243
244 ret = comps_hslist_create();
245 comps_hslist_init(ret, hslist->data_constructor,
246 hslist->data_cloner,
247 hslist->data_destructor);
248 for (it = hslist->first; it != NULL; it = it->next) {
249 comps_hslist_append(ret, hslist->data_cloner(it->data), 0);
250 }
251 return ret;
252 }
253
comps_hslist_clear(COMPS_HSList * hslist)254 void comps_hslist_clear(COMPS_HSList * hslist) {
255 COMPS_HSListItem *it,*oldit;
256 if (hslist == NULL) return;
257 oldit = hslist->first;
258 it = (oldit)?oldit->next:NULL;
259 for (;it != NULL; it=it->next) {
260 if (hslist->data_destructor != NULL)
261 hslist->data_destructor(oldit->data);
262 free(oldit);
263 oldit = it;
264 }
265 if (oldit) {
266 if (hslist->data_destructor != NULL)
267 hslist->data_destructor(oldit->data);
268 free(oldit);
269 }
270 hslist->first = NULL;
271 hslist->last = NULL;
272 }
273
comps_hslist_values_equal(COMPS_HSList * hlist1,COMPS_HSList * hlist2,char (* cmpf)(void *,void *))274 unsigned comps_hslist_values_equal(COMPS_HSList *hlist1, COMPS_HSList *hlist2,
275 char (*cmpf)(void*, void*)) {
276 COMPS_HSListItem *it, *it2;
277 for (it = hlist1->first, it2 = hlist2->first; it != NULL && it2 != NULL;
278 it = it->next, it2 = it2->next) {
279 if (!cmpf(it->data, it2->data))
280 return 0;
281 }
282 if (it != NULL || it2 != NULL)
283 return 0;
284 return 1;
285 }
286
comps_hslist_unique(COMPS_HSList * hlist,char (* cmpf)(void *,void *))287 void comps_hslist_unique(COMPS_HSList *hlist, char (*cmpf)(void*, void*)) {
288 COMPS_Set *set;
289 COMPS_HSListItem *it, *it2;
290
291 if (hlist == NULL) return;
292
293 set = comps_set_create();
294 comps_set_init(set, NULL, NULL, NULL, cmpf);
295 it2 = NULL;
296 for (it = hlist->first; it != NULL; it2 = it, it = it->next) {
297 if (!comps_set_in(set, it->data)) {
298 comps_set_add(set, it->data);
299 } else {
300 hlist->data_destructor(it->data);
301 }
302 free(it2);
303 }
304 free(it2);
305 hlist->first = set->data->first;
306 hlist->last = set->data->last;
307 free(set->data);
308 free(set);
309 }
310