Add/remove source(s) in our MSVC project (libardour)
[ardour.git] / libs / fluidsynth / src / fluid_list.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 /*
21  * Modified by the GLib Team and others 1997-1999.  See the AUTHORS
22  * file for a list of people on the GLib Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GLib at ftp://ftp.gtk.org/pub/gtk/.
25  */
26
27
28
29 #include "fluid_sys.h"
30 #include "fluid_list.h"
31
32
33 fluid_list_t *
34 new_fluid_list(void)
35 {
36     fluid_list_t *list;
37     list = (fluid_list_t *) FLUID_MALLOC(sizeof(fluid_list_t));
38     list->data = NULL;
39     list->next = NULL;
40     return list;
41 }
42
43 void
44 delete_fluid_list(fluid_list_t *list)
45 {
46     fluid_list_t *next;
47     fluid_return_if_fail(list != NULL);
48
49     while(list)
50     {
51         next = list->next;
52         FLUID_FREE(list);
53         list = next;
54     }
55 }
56
57 void
58 delete1_fluid_list(fluid_list_t *list)
59 {
60     FLUID_FREE(list);
61 }
62
63 fluid_list_t *
64 fluid_list_append(fluid_list_t *list, void  *data)
65 {
66     fluid_list_t *new_list;
67     fluid_list_t *last;
68
69     new_list = new_fluid_list();
70     new_list->data = data;
71
72     if(list)
73     {
74         last = fluid_list_last(list);
75         /* g_assert (last != NULL); */
76         last->next = new_list;
77
78         return list;
79     }
80     else
81     {
82         return new_list;
83     }
84 }
85
86 fluid_list_t *
87 fluid_list_prepend(fluid_list_t *list, void *data)
88 {
89     fluid_list_t *new_list;
90
91     new_list = new_fluid_list();
92     new_list->data = data;
93     new_list->next = list;
94
95     return new_list;
96 }
97
98 fluid_list_t *
99 fluid_list_nth(fluid_list_t *list, int n)
100 {
101     while((n-- > 0) && list)
102     {
103         list = list->next;
104     }
105
106     return list;
107 }
108
109 fluid_list_t *
110 fluid_list_remove(fluid_list_t *list, void *data)
111 {
112     fluid_list_t *tmp;
113     fluid_list_t *prev;
114
115     prev = NULL;
116     tmp = list;
117
118     while(tmp)
119     {
120         if(tmp->data == data)
121         {
122             if(prev)
123             {
124                 prev->next = tmp->next;
125             }
126
127             if(list == tmp)
128             {
129                 list = list->next;
130             }
131
132             tmp->next = NULL;
133             delete_fluid_list(tmp);
134
135             break;
136         }
137
138         prev = tmp;
139         tmp = tmp->next;
140     }
141
142     return list;
143 }
144
145 fluid_list_t *
146 fluid_list_remove_link(fluid_list_t *list, fluid_list_t *link)
147 {
148     fluid_list_t *tmp;
149     fluid_list_t *prev;
150
151     prev = NULL;
152     tmp = list;
153
154     while(tmp)
155     {
156         if(tmp == link)
157         {
158             if(prev)
159             {
160                 prev->next = tmp->next;
161             }
162
163             if(list == tmp)
164             {
165                 list = list->next;
166             }
167
168             tmp->next = NULL;
169             break;
170         }
171
172         prev = tmp;
173         tmp = tmp->next;
174     }
175
176     return list;
177 }
178
179 static fluid_list_t *
180 fluid_list_sort_merge(fluid_list_t *l1, fluid_list_t *l2, fluid_compare_func_t compare_func)
181 {
182     fluid_list_t list, *l;
183
184     l = &list;
185
186     while(l1 && l2)
187     {
188         if(compare_func(l1->data, l2->data) < 0)
189         {
190             l = l->next = l1;
191             l1 = l1->next;
192         }
193         else
194         {
195             l = l->next = l2;
196             l2 = l2->next;
197         }
198     }
199
200     l->next = l1 ? l1 : l2;
201
202     return list.next;
203 }
204
205 fluid_list_t *
206 fluid_list_sort(fluid_list_t *list, fluid_compare_func_t compare_func)
207 {
208     fluid_list_t *l1, *l2;
209
210     if(!list)
211     {
212         return NULL;
213     }
214
215     if(!list->next)
216     {
217         return list;
218     }
219
220     l1 = list;
221     l2 = list->next;
222
223     while((l2 = l2->next) != NULL)
224     {
225         if((l2 = l2->next) == NULL)
226         {
227             break;
228         }
229
230         l1 = l1->next;
231     }
232
233     l2 = l1->next;
234     l1->next = NULL;
235
236     return fluid_list_sort_merge(fluid_list_sort(list, compare_func),
237                                  fluid_list_sort(l2, compare_func),
238                                  compare_func);
239 }
240
241
242 fluid_list_t *
243 fluid_list_last(fluid_list_t *list)
244 {
245     if(list)
246     {
247         while(list->next)
248         {
249             list = list->next;
250         }
251     }
252
253     return list;
254 }
255
256 int
257 fluid_list_size(fluid_list_t *list)
258 {
259     int n = 0;
260
261     while(list)
262     {
263         n++;
264         list = list->next;
265     }
266
267     return n;
268 }
269
270 fluid_list_t *fluid_list_insert_at(fluid_list_t *list, int n, void *data)
271 {
272     fluid_list_t *new_list;
273     fluid_list_t *cur;
274     fluid_list_t *prev = NULL;
275
276     new_list = new_fluid_list();
277     new_list->data = data;
278
279     cur = list;
280
281     while((n-- > 0) && cur)
282     {
283         prev = cur;
284         cur = cur->next;
285     }
286
287     new_list->next = cur;
288
289     if(prev)
290     {
291         prev->next = new_list;
292         return list;
293     }
294     else
295     {
296         return new_list;
297     }
298 }
299
300 /* Compare function to sort strings alphabetically,
301  * for use with fluid_list_sort(). */
302 int
303 fluid_list_str_compare_func(void *a, void *b)
304 {
305     if(a && b)
306     {
307         return FLUID_STRCMP((char *)a, (char *)b);
308     }
309
310     if(!a && !b)
311     {
312         return 0;
313     }
314
315     if(a)
316     {
317         return -1;
318     }
319
320     return 1;
321 }