tsst
[skippy-xd] / dlist.c
1 /* Skippy - Seduces Kids Into Perversion
2  *
3  * Copyright (C) 2004 Hyriand <hyriand@thegraveyard.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include "skippy.h"
21
22 dlist *
23 dlist_last(dlist *l)
24 {
25         while(l && l->next)
26                 l = l->next;
27         return l;
28 }
29
30 dlist *
31 dlist_first(dlist *l)
32 {
33         while(l && l->prev)
34                 l = l->prev;
35         return l;
36 }
37
38 dlist *
39 dlist_add(dlist *l, void *d)
40 {
41         dlist *new_elem;
42         
43         l = dlist_last(l);
44         new_elem = malloc(sizeof(dlist));
45         new_elem->prev = l;
46         new_elem->next = 0;
47         new_elem->data = d;
48         if(l)
49                 l->next = new_elem;
50         return new_elem;
51 }
52
53 dlist *
54 dlist_prepend(dlist *l, void *d)
55 {
56         dlist *new_elem;
57         l = dlist_first(l);
58         new_elem = malloc(sizeof(dlist));
59         new_elem->prev = 0;
60         new_elem->next = l;
61         new_elem->data = d;
62         if(l)
63                 l->prev = new_elem;
64         return new_elem;
65 }
66
67 dlist *
68 dlist_remove(dlist *l)
69 {
70         dlist *n = 0;
71         
72         if(! l)
73                 return 0;
74         
75         if(l->prev) {
76                 n = l->prev;
77                 l->prev->next = l->next;
78         }
79         if(l->next) {
80                 n = l->next;
81                 l->next->prev = l->prev;
82         }
83         free(l);
84         return n;
85 }
86
87 dlist *
88 dlist_remove_free_data(dlist *l)
89 {
90         if(l && l->data)
91                 free(l->data);
92         return dlist_remove(l);
93 }
94
95 dlist *
96 dlist_remove_nth(dlist *l, unsigned int n)
97 {
98         return dlist_remove(dlist_nth(l, n));
99 }
100
101 dlist *
102 dlist_remove_nth_free_data(dlist *l, unsigned int n)
103 {
104         return dlist_remove_free_data(dlist_nth(l, n));
105 }
106
107 int
108 dlist_same(dlist *l1, dlist *l2)
109 {
110         l1 = dlist_first(l1);
111         while(l1) {
112                 if(l1 == l2)
113                         return 1;
114                 l1 = l1->next;
115         }
116         return 0;
117 }
118
119 void
120 dlist_reverse(dlist *l)
121 {
122         dlist *iter1 = dlist_first(l),
123                 *iter2 = dlist_last(l);
124         
125         while(iter1 != iter2) {
126                 dlist_swap(iter1, iter2);
127                 if(iter1->next == iter2)
128                         break;
129                 iter1 = iter1->next;
130                 iter2 = iter2->prev;
131         }
132 }
133
134 dlist *
135 dlist_free(dlist *l)
136 {
137         l = dlist_first(l);
138         
139         while(l) {
140                 dlist *c = l;
141                 l = l->next;
142                 free(c);
143         }
144         
145         return 0;
146 }
147
148 dlist *
149 dlist_dup(dlist *l)
150 {
151         dlist *n = 0;
152         l = dlist_first(l);
153         
154         while(l) {
155                 n = dlist_add(n, l->data);
156                 l = l->next;
157         }
158         
159         return n;
160 }
161
162 dlist *
163 dlist_find_all(dlist *l, dlist_match_func match, void *data)
164 {
165         dlist *n = 0;
166         l = dlist_first(l);
167         
168         while(l) {
169                 if(match(l, data))
170                         n = dlist_add(n, l->data);
171                 l = l->next;
172         }
173         
174         return n;
175 }
176
177 dlist *
178 dlist_find(dlist *l, dlist_match_func func, void *data)
179 {
180         for(l = dlist_first(l); l; l = l->next)
181                 if(func(l, data))
182                         break;
183         return l;
184 }
185
186 dlist *
187 dlist_find_data(dlist *l, void *data)
188 {
189         for(l = dlist_first(l); l; l = l->next)
190                 if(l->data == data)
191                         break;
192         return l;
193 }
194
195 void
196 dlist_free_data(dlist *l)
197 {
198         l = dlist_first(l);
199         
200         while(l) {
201                 if(l->data)
202                         free(l->data);
203                 l->data = 0;
204                 l = l->next;
205         }
206 }
207
208 dlist *
209 dlist_free_with_data(dlist *l)
210 {
211         l = dlist_first(l);
212         
213         while(l) {
214                 dlist *c = l;
215                 if(l->data)
216                         free(l->data);
217                 l = l->next;
218                 free(c);
219         }
220         
221         return 0;
222 }
223
224 dlist *
225 dlist_free_with_func(dlist *l, dlist_free_func func)
226 {
227         l = dlist_first(l);
228         
229         while(l) {
230                 dlist *c = l;
231                 if(l->data)
232                         func(l->data);
233                 l = l->next;
234                 free(c);
235         }
236         
237         return 0;
238 }
239
240 unsigned int
241 dlist_len(dlist *l)
242 {
243         unsigned int n = 0;
244         
245         l = dlist_first(l);
246         while(l) {
247                 n++;
248                 l = l->next;
249         }
250         
251         return n;
252 }
253
254 dlist *
255 dlist_nth(dlist *l, unsigned int n)
256 {
257         unsigned int i = 0;
258         l = dlist_first(l);
259         while(l && i != n) {
260                 i++;
261                 l = l->next;
262         }
263         
264         return l;
265 }
266
267 void
268 dlist_swap(dlist *l1, dlist *l2)
269 {
270         void *tmp = l1->data;
271         l1->data = l2->data;
272         l2->data = tmp;
273 }
274
275 void
276 dlist_sort(dlist *l, dlist_cmp_func cmp, void *data)
277 {
278         dlist *start = dlist_first(l);
279         while(start) {
280                 dlist *iter = start;
281                 start = 0;
282                 while(iter) {
283                         if(iter->next && cmp(iter, iter->next, data) == 1) {
284                                 dlist_swap(iter, iter->next);
285                                 if(! start)
286                                         start = iter->prev;
287                         }
288                         iter = iter->next;
289                 }
290         }
291 }
292