dd47a39e0e215e60b5fbbf861c1f5bdc8287242d
[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 Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library 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_list.h"
30
31
32 fluid_list_t*
33 new_fluid_list(void)
34 {
35   fluid_list_t* list;
36   list = (fluid_list_t*) FLUID_MALLOC(sizeof(fluid_list_t));
37   list->data = NULL;
38   list->next = NULL;
39   return list;
40 }
41
42 void
43 delete_fluid_list(fluid_list_t *list)
44 {
45   fluid_list_t *next;
46   while (list) {
47     next = list->next;
48     FLUID_FREE(list);
49     list = next;
50   }
51 }
52
53 void
54 delete1_fluid_list(fluid_list_t *list)
55 {
56   if (list) {
57     FLUID_FREE(list);
58   }
59 }
60
61 fluid_list_t*
62 fluid_list_append(fluid_list_t *list, void*  data)
63 {
64   fluid_list_t *new_list;
65   fluid_list_t *last;
66
67   new_list = new_fluid_list();
68   new_list->data = data;
69
70   if (list)
71     {
72       last = fluid_list_last(list);
73       /* g_assert (last != NULL); */
74       last->next = new_list;
75
76       return list;
77     }
78   else
79       return new_list;
80 }
81
82 fluid_list_t*
83 fluid_list_prepend(fluid_list_t *list, void* data)
84 {
85   fluid_list_t *new_list;
86
87   new_list = new_fluid_list();
88   new_list->data = data;
89   new_list->next = list;
90
91   return new_list;
92 }
93
94 fluid_list_t*
95 fluid_list_nth(fluid_list_t *list, int n)
96 {
97   while ((n-- > 0) && list) {
98     list = list->next;
99   }
100
101   return list;
102 }
103
104 fluid_list_t*
105 fluid_list_remove(fluid_list_t *list, void* data)
106 {
107   fluid_list_t *tmp;
108   fluid_list_t *prev;
109
110   prev = NULL;
111   tmp = list;
112
113   while (tmp) {
114     if (tmp->data == data) {
115       if (prev) {
116         prev->next = tmp->next;
117       }
118       if (list == tmp) {
119         list = list->next;
120       }
121       tmp->next = NULL;
122       delete_fluid_list(tmp);
123
124       break;
125     }
126
127     prev = tmp;
128     tmp = tmp->next;
129   }
130
131   return list;
132 }
133
134 fluid_list_t*
135 fluid_list_remove_link(fluid_list_t *list, fluid_list_t *link)
136 {
137   fluid_list_t *tmp;
138   fluid_list_t *prev;
139
140   prev = NULL;
141   tmp = list;
142
143   while (tmp) {
144     if (tmp == link) {
145       if (prev) {
146         prev->next = tmp->next;
147       }
148       if (list == tmp) {
149         list = list->next;
150       }
151       tmp->next = NULL;
152       break;
153     }
154
155     prev = tmp;
156     tmp = tmp->next;
157   }
158
159   return list;
160 }
161
162 static fluid_list_t*
163 fluid_list_sort_merge(fluid_list_t *l1, fluid_list_t *l2, fluid_compare_func_t compare_func)
164 {
165   fluid_list_t list, *l;
166
167   l = &list;
168
169   while (l1 && l2) {
170     if (compare_func(l1->data,l2->data) < 0) {
171       l = l->next = l1;
172       l1 = l1->next;
173     } else {
174       l = l->next = l2;
175       l2 = l2->next;
176     }
177   }
178   l->next= l1 ? l1 : l2;
179
180   return list.next;
181 }
182
183 fluid_list_t*
184 fluid_list_sort(fluid_list_t *list, fluid_compare_func_t compare_func)
185 {
186   fluid_list_t *l1, *l2;
187
188   if (!list) {
189     return NULL;
190   }
191   if (!list->next) {
192     return list;
193   }
194
195   l1 = list;
196   l2 = list->next;
197
198   while ((l2 = l2->next) != NULL) {
199     if ((l2 = l2->next) == NULL)
200       break;
201     l1=l1->next;
202   }
203   l2 = l1->next;
204   l1->next = NULL;
205
206   return fluid_list_sort_merge(fluid_list_sort(list, compare_func),
207                               fluid_list_sort(l2, compare_func),
208                               compare_func);
209 }
210
211
212 fluid_list_t*
213 fluid_list_last(fluid_list_t *list)
214 {
215   if (list) {
216     while (list->next)
217       list = list->next;
218   }
219
220   return list;
221 }
222
223 int
224 fluid_list_size(fluid_list_t *list)
225 {
226   int n = 0;
227   while (list) {
228     n++;
229     list = list->next;
230   }
231   return n;
232 }
233
234 fluid_list_t* fluid_list_insert_at(fluid_list_t *list, int n, void* data)
235 {
236   fluid_list_t *new_list;
237   fluid_list_t *cur;
238   fluid_list_t *prev = NULL;
239
240   new_list = new_fluid_list();
241   new_list->data = data;
242
243   cur = list;
244   while ((n-- > 0) && cur) {
245     prev = cur;
246     cur = cur->next;
247   }
248
249   new_list->next = cur;
250
251   if (prev) {
252     prev->next = new_list;
253     return list;
254   } else {
255     return new_list;
256   }
257 }
258
259 /* Compare function to sort strings alphabetically,
260  * for use with fluid_list_sort(). */
261 int
262 fluid_list_str_compare_func (void *a, void *b)
263 {
264   if (a && b) return FLUID_STRCMP ((char *)a, (char *)b);
265   if (!a && !b) return 0;
266   if (a) return -1;
267   return 1;
268 }