Make mono_fmod extern "C and not static, to simplify later (#14355)
[mono-project.git] / mono / eglib / gslist.c
blob1293564df1b4132ad4e2693938248e2ca312155b
1 /*
2 * gslist.c: Singly-linked list implementation
4 * Authors:
5 * Duncan Mak (duncan@novell.com)
6 * Raja R Harinath (rharinath@novell.com)
8 * Permission is hereby granted, free of charge, to any person obtaining
9 * a copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
16 * The above copyright notice and this permission notice shall be
17 * included in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * (C) 2006 Novell, Inc.
29 #include "config.h"
30 #include <stdio.h>
31 #include <glib.h>
33 GSList*
34 g_slist_alloc (void)
36 return g_new0 (GSList, 1);
39 void
40 g_slist_free_1 (GSList *list)
42 g_free (list);
45 GSList*
46 g_slist_append (GSList *list, gpointer data)
48 return g_slist_concat (list, g_slist_prepend (NULL, data));
51 /* This is also a list node constructor. */
52 GSList*
53 g_slist_prepend (GSList *list, gpointer data)
55 GSList *head = g_slist_alloc ();
56 head->data = data;
57 head->next = list;
59 return head;
63 * Insert the given data in a new node after the current node.
64 * Return new node.
66 static inline GSList *
67 insert_after (GSList *list, gpointer data)
69 list->next = g_slist_prepend (list->next, data);
70 return list->next;
74 * Return the node prior to the node containing 'data'.
75 * If the list is empty, or the first node contains 'data', return NULL.
76 * If no node contains 'data', return the last node.
78 static inline GSList*
79 find_prev (GSList *list, gconstpointer data)
81 GSList *prev = NULL;
82 while (list) {
83 if (list->data == data)
84 break;
85 prev = list;
86 list = list->next;
88 return prev;
91 /* like 'find_prev', but searches for node 'link' */
92 static inline GSList*
93 find_prev_link (GSList *list, GSList *link)
95 GSList *prev = NULL;
96 while (list) {
97 if (list == link)
98 break;
99 prev = list;
100 list = list->next;
102 return prev;
105 GSList*
106 g_slist_insert_before (GSList *list, GSList *sibling, gpointer data)
108 GSList *prev = find_prev_link (list, sibling);
110 if (!prev)
111 return g_slist_prepend (list, data);
113 insert_after (prev, data);
114 return list;
117 void
118 g_slist_free (GSList *list)
120 while (list) {
121 GSList *next = list->next;
122 g_slist_free_1 (list);
123 list = next;
127 GSList*
128 g_slist_copy (GSList *list)
130 GSList *copy, *tmp;
132 if (!list)
133 return NULL;
135 copy = g_slist_prepend (NULL, list->data);
136 tmp = copy;
138 for (list = list->next; list; list = list->next)
139 tmp = insert_after (tmp, list->data);
141 return copy;
144 GSList*
145 g_slist_concat (GSList *list1, GSList *list2)
147 if (!list1)
148 return list2;
150 g_slist_last (list1)->next = list2;
151 return list1;
154 void
155 g_slist_foreach (GSList *list, GFunc func, gpointer user_data)
157 while (list) {
158 (*func) (list->data, user_data);
159 list = list->next;
163 GSList*
164 g_slist_last (GSList *list)
166 if (!list)
167 return NULL;
169 while (list->next)
170 list = list->next;
172 return list;
175 GSList*
176 g_slist_find (GSList *list, gconstpointer data)
178 for (; list; list = list->next)
179 if (list->data == data)
180 break;
181 return list;
184 GSList *
185 g_slist_find_custom (GSList *list, gconstpointer data, GCompareFunc func)
187 if (!func)
188 return NULL;
190 while (list) {
191 if (func (list->data, data) == 0)
192 return list;
194 list = list->next;
197 return NULL;
200 guint
201 g_slist_length (GSList *list)
203 guint length = 0;
205 while (list) {
206 length ++;
207 list = list->next;
210 return length;
213 GSList*
214 g_slist_remove (GSList *list, gconstpointer data)
216 GSList *prev = find_prev (list, data);
217 GSList *current = prev ? prev->next : list;
219 if (current) {
220 if (prev)
221 prev->next = current->next;
222 else
223 list = current->next;
224 g_slist_free_1 (current);
227 return list;
230 GSList*
231 g_slist_remove_all (GSList *list, gconstpointer data)
233 GSList *next = list;
234 GSList *prev = NULL;
235 GSList *current;
237 while (next) {
238 GSList *tmp_prev = find_prev (next, data);
239 if (tmp_prev)
240 prev = tmp_prev;
241 current = prev ? prev->next : list;
243 if (!current)
244 break;
246 next = current->next;
248 if (prev)
249 prev->next = next;
250 else
251 list = next;
252 g_slist_free_1 (current);
255 return list;
258 GSList*
259 g_slist_remove_link (GSList *list, GSList *link)
261 GSList *prev = find_prev_link (list, link);
262 GSList *current = prev ? prev->next : list;
264 if (current) {
265 if (prev)
266 prev->next = current->next;
267 else
268 list = current->next;
269 current->next = NULL;
272 return list;
275 GSList*
276 g_slist_delete_link (GSList *list, GSList *link)
278 list = g_slist_remove_link (list, link);
279 g_slist_free_1 (link);
281 return list;
284 GSList*
285 g_slist_reverse (GSList *list)
287 GSList *prev = NULL;
288 while (list){
289 GSList *next = list->next;
290 list->next = prev;
291 prev = list;
292 list = next;
295 return prev;
298 GSList*
299 g_slist_insert_sorted (GSList *list, gpointer data, GCompareFunc func)
301 GSList *prev = NULL;
303 if (!func)
304 return list;
306 if (!list || func (list->data, data) > 0)
307 return g_slist_prepend (list, data);
309 /* Invariant: func (prev->data, data) <= 0) */
310 for (prev = list; prev->next; prev = prev->next)
311 if (func (prev->next->data, data) > 0)
312 break;
314 /* ... && (prev->next == 0 || func (prev->next->data, data) > 0)) */
315 insert_after (prev, data);
316 return list;
319 gint
320 g_slist_index (GSList *list, gconstpointer data)
322 gint index = 0;
324 while (list) {
325 if (list->data == data)
326 return index;
328 index++;
329 list = list->next;
332 return -1;
335 GSList*
336 g_slist_nth (GSList *list, guint n)
338 for (; list; list = list->next) {
339 if (n == 0)
340 break;
341 n--;
343 return list;
346 gpointer
347 g_slist_nth_data (GSList *list, guint n)
349 GSList *node = g_slist_nth (list, n);
350 return node ? node->data : NULL;
353 typedef GSList list_node;
354 #include "sort.frag.h"
356 GSList*
357 g_slist_sort (GSList *list, GCompareFunc func)
359 if (!list || !list->next)
360 return list;
361 return do_sort (list, func);