2 * glist.c: Doubly-linked list implementation
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.
35 return g_new0 (GList
, 1);
39 new_node (GList
*prev
, gpointer data
, GList
*next
)
41 GList
*node
= g_list_alloc ();
53 disconnect_node (GList
*node
)
56 node
->next
->prev
= node
->prev
;
58 node
->prev
->next
= node
->next
;
63 g_list_prepend (GList
*list
, gpointer data
)
65 return new_node (list
? list
->prev
: NULL
, data
, list
);
69 g_list_free_1 (GList
*list
)
75 g_list_free (GList
*list
)
78 GList
*next
= list
->next
;
85 g_list_append (GList
*list
, gpointer data
)
87 GList
*node
= new_node (g_list_last (list
), data
, NULL
);
88 return list
? list
: node
;
92 g_list_concat (GList
*list1
, GList
*list2
)
95 list2
->prev
= g_list_last (list1
);
96 list2
->prev
->next
= list2
;
98 return list1
? list1
: list2
;
102 g_list_length (GList
*list
)
115 g_list_remove (GList
*list
, gconstpointer data
)
117 GList
*current
= g_list_find (list
, data
);
123 g_list_free_1 (disconnect_node (current
));
129 g_list_remove_link (GList
*list
, GList
*link
)
134 disconnect_node (link
);
142 g_list_delete_link (GList
*list
, GList
*link
)
144 list
= g_list_remove_link (list
, link
);
145 g_list_free_1 (link
);
151 g_list_find (GList
*list
, gconstpointer data
)
154 if (list
->data
== data
)
164 g_list_reverse (GList
*list
)
166 GList
*reverse
= NULL
;
170 list
= reverse
->next
;
172 reverse
->next
= reverse
->prev
;
173 reverse
->prev
= list
;
180 g_list_first (GList
*list
)
192 g_list_last (GList
*list
)
204 g_list_insert_sorted (GList
*list
, gpointer data
, GCompareFunc func
)
213 /* Invariant: !prev || func (prev->data, data) <= 0) */
214 for (current
= list
; current
; current
= current
->next
) {
215 if (func (current
->data
, data
) > 0)
220 node
= new_node (prev
, data
, current
);
221 return list
== current
? node
: list
;
225 g_list_insert_before (GList
*list
, GList
*sibling
, gpointer data
)
228 GList
*node
= new_node (sibling
->prev
, data
, sibling
);
229 return list
== sibling
? node
: list
;
231 return g_list_append (list
, data
);
235 g_list_foreach (GList
*list
, GFunc func
, gpointer user_data
)
238 (*func
) (list
->data
, user_data
);
244 g_list_index (GList
*list
, gconstpointer data
)
249 if (list
->data
== data
)
260 g_list_nth (GList
*list
, guint n
)
262 for (; list
; list
= list
->next
) {
271 g_list_nth_data (GList
*list
, guint n
)
273 GList
*node
= g_list_nth (list
, n
);
274 return node
? node
->data
: NULL
;
278 g_list_copy (GList
*list
)
283 GList
*tmp
= new_node (NULL
, list
->data
, NULL
);
286 for (list
= list
->next
; list
; list
= list
->next
)
287 tmp
= new_node (tmp
, list
->data
, NULL
);
293 typedef GList list_node
;
294 #include "sort.frag.h"
297 g_list_sort (GList
*list
, GCompareFunc func
)
300 if (!list
|| !list
->next
)
302 list
= do_sort (list
, func
);
304 /* Fixup: do_sort doesn't update 'prev' pointers */
306 for (current
= list
; current
->next
; current
= current
->next
)
307 current
->next
->prev
= current
;