1 /*
2   Based on gslist.c from glib-1.2.9 (LGPL).
3 
4   Adaption to JACK, Copyright (C) 2002 Kai Vehmanen.
5     - replaced use of gtypes with normal ANSI C types
6     - glib's memory allocation routines replaced with
7       malloc/free calls
8 
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU Lesser General Public License as published by
11   the Free Software Foundation; either version 2.1 of the License, or
12   (at your option) any later version.
13 
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU Lesser General Public License for more details.
18 
19   You should have received a copy of the GNU Lesser General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 
23 */
24 
25 module jack.c.jslist;
26 public import jack.c.systemdeps;
27 import core.stdc.stdlib;
28 
29 extern(C)
30 {
31 
32 alias JCompareFunc = int function(void* a, void* b);
33 struct JSList
34 {
35     void *data;
36     JSList *next;
37 };
38 
39 // pragma(inline, true)
40 static
41 JSList*
42 jack_slist_alloc ()
43 {
44     JSList *new_list;
45 
46     new_list = cast(JSList*)malloc(JSList.sizeof);
47     if (new_list) {
48         new_list.data = null;
49         new_list.next = null;
50     }
51 
52     return new_list;
53 }
54 
55 // pragma(inline, true)
56 static
57 JSList*
58 jack_slist_prepend (JSList* list, void* data)
59 {
60     JSList *new_list;
61 
62     new_list = cast(JSList*)malloc(JSList.sizeof);
63     if (new_list) {
64         new_list.data = data;
65         new_list.next = list;
66     }
67 
68     return new_list;
69 }
70 
71 // pragma(inline, true)
72 static
73 JSList*
74 jack_slist_next (JSList *slist)
75 {
76   return slist ? slist.next : null;
77 }
78 
79 // pragma(inline, true)
80 static
81 JSList*
82 jack_slist_last (JSList *list)
83 {
84     if (list) {
85         while (list.next)
86             list = list.next;
87     }
88 
89     return list;
90 }
91 
92 // pragma(inline, true)
93 static
94 JSList*
95 jack_slist_remove_link (JSList *list,
96                         JSList *link)
97 {
98     JSList *tmp;
99     JSList *prev;
100 
101     prev = null;
102     tmp = list;
103 
104     while (tmp) {
105         if (tmp == link) {
106             if (prev)
107                 prev.next = tmp.next;
108             if (list == tmp)
109                 list = list.next;
110 
111             tmp.next = null;
112             break;
113         }
114 
115         prev = tmp;
116         tmp = tmp.next;
117     }
118 
119     return list;
120 }
121 
122 // pragma(inline, true)
123 static
124 void
125 jack_slist_free (JSList *list)
126 {
127     while (list) {
128         JSList *next = list.next;
129         free(list);
130         list = next;
131     }
132 }
133 
134 // pragma(inline, true)
135 static
136 void
137 jack_slist_free_1 (JSList *list)
138 {
139     if (list) {
140         free(list);
141     }
142 }
143 
144 // pragma(inline, true)
145 static
146 JSList*
147 jack_slist_remove (JSList *list,
148                    void *data)
149 {
150     JSList *tmp;
151     JSList *prev;
152 
153     prev = null;
154     tmp = list;
155 
156     while (tmp) {
157         if (tmp.data == data) {
158             if (prev)
159                 prev.next = tmp.next;
160             if (list == tmp)
161                 list = list.next;
162 
163             tmp.next = null;
164             jack_slist_free (tmp);
165 
166             break;
167         }
168 
169         prev = tmp;
170         tmp = tmp.next;
171     }
172 
173     return list;
174 }
175 
176 // pragma(inline, true)
177 static
178 uint
179 jack_slist_length (JSList *list)
180 {
181     uint length;
182 
183     length = 0;
184     while (list) {
185         length++;
186         list = list.next;
187     }
188 
189     return length;
190 }
191 
192 // pragma(inline, true)
193 static
194 JSList*
195 jack_slist_find (JSList *list,
196                  void *data)
197 {
198     while (list) {
199         if (list.data == data)
200             break;
201         list = list.next;
202     }
203 
204     return list;
205 }
206 
207 // pragma(inline, true)
208 static
209 JSList*
210 jack_slist_copy (JSList *list)
211 {
212     JSList *new_list = null;
213 
214     if (list) {
215         JSList *last;
216 
217         new_list = jack_slist_alloc ();
218         new_list.data = list.data;
219         last = new_list;
220         list = list.next;
221         while (list) {
222             last.next = jack_slist_alloc ();
223             last = last.next;
224             last.data = list.data;
225             list = list.next;
226         }
227     }
228 
229     return new_list;
230 }
231 
232 // pragma(inline, true)
233 static
234 JSList*
235 jack_slist_append (JSList *list,
236                    void *data)
237 {
238     JSList *new_list;
239     JSList *last;
240 
241     new_list = jack_slist_alloc ();
242     new_list.data = data;
243 
244     if (list) {
245         last = jack_slist_last (list);
246         last.next = new_list;
247 
248         return list;
249     } else
250         return new_list;
251 }
252 
253 // pragma(inline, true)
254 static
255 JSList*
256 jack_slist_sort_merge (JSList *l1,
257                        JSList *l2,
258                        JCompareFunc compare_func)
259 {
260     JSList list;
261     JSList *l;
262 
263     l = &list;
264 
265     while (l1 && l2) {
266         if (compare_func(l1.data, l2.data) < 0) {
267             l = l.next = l1;
268             l1 = l1.next;
269         } else {
270             l = l.next = l2;
271             l2 = l2.next;
272         }
273     }
274     l.next = l1 ? l1 : l2;
275 
276     return list.next;
277 }
278 
279 // pragma(inline, true)
280 static
281 JSList*
282 jack_slist_sort (JSList *list,
283                  JCompareFunc compare_func)
284 {
285     JSList *l1;
286     JSList *l2;
287 
288     if (!list)
289         return null;
290     if (!list.next)
291         return list;
292 
293     l1 = list;
294     l2 = list.next;
295 
296     while ((l2 = l2.next) != null) {
297         if ((l2 = l2.next) == null)
298             break;
299         l1 = l1.next;
300     }
301     l2 = l1.next;
302     l1.next = null;
303 
304     return jack_slist_sort_merge (jack_slist_sort (list, compare_func),
305                                   jack_slist_sort (l2, compare_func),
306                                   compare_func);
307 }
308 
309 }