]> Pileus Git - ~andy/gtk/blob - glib/glist.c
Initial revision
[~andy/gtk] / glib / glist.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 Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 #include "glib.h"
19
20
21 typedef struct _GRealListAllocator GRealListAllocator;
22
23 struct _GRealListAllocator
24 {
25   GMemChunk *list_mem_chunk;
26   GList     *free_list;
27 };
28
29
30 static GRealListAllocator *default_allocator = NULL;
31 static GRealListAllocator *current_allocator = NULL;
32
33
34 GListAllocator*
35 g_list_allocator_new ()
36 {
37   GRealListAllocator* allocator = g_new (GRealListAllocator, 1);
38
39   allocator->list_mem_chunk = NULL;
40   allocator->free_list = NULL;
41
42   return (GListAllocator*) allocator;
43 }
44
45 void
46 g_list_allocator_free (GListAllocator* fallocator)
47 {
48   GRealListAllocator* allocator = (GRealListAllocator *) fallocator;
49
50   if (allocator && allocator->list_mem_chunk)
51     g_mem_chunk_destroy (allocator->list_mem_chunk);
52   if (allocator)
53     g_free (allocator);
54 }
55
56 GListAllocator*
57 g_list_set_allocator (GListAllocator* fallocator)
58 {
59   GRealListAllocator* allocator = (GRealListAllocator *) fallocator;
60   GRealListAllocator* old_allocator = current_allocator;
61
62   if (allocator)
63     current_allocator = allocator;
64   else
65     {
66       if (!default_allocator)
67         default_allocator = (GRealListAllocator*) g_list_allocator_new ();
68       current_allocator = default_allocator;
69     }
70
71   if (!current_allocator->list_mem_chunk)
72     current_allocator->list_mem_chunk = g_mem_chunk_new ("list mem chunk",
73                                                          sizeof (GList),
74                                                          1024,
75                                                          G_ALLOC_ONLY);
76
77   return (GListAllocator*) (old_allocator == default_allocator ? NULL : old_allocator);
78 }
79
80
81 GList*
82 g_list_alloc ()
83 {
84   GList *new_list;
85
86   g_list_set_allocator (NULL);
87   if (current_allocator->free_list)
88     {
89       new_list = current_allocator->free_list;
90       current_allocator->free_list = current_allocator->free_list->next;
91     }
92   else
93     {
94       new_list = g_chunk_new (GList, current_allocator->list_mem_chunk);
95     }
96
97   new_list->data = NULL;
98   new_list->next = NULL;
99   new_list->prev = NULL;
100
101   return new_list;
102 }
103
104 void
105 g_list_free (GList *list)
106 {
107   GList *last;
108
109   if (list)
110     {
111       last = g_list_last (list);
112       last->next = current_allocator->free_list;
113       current_allocator->free_list = list;
114     }
115 }
116
117 void
118 g_list_free_1 (GList *list)
119 {
120   if (list)
121     {
122       list->next = current_allocator->free_list;
123       current_allocator->free_list = list;
124     }
125 }
126
127 GList*
128 g_list_append (GList    *list,
129                gpointer  data)
130 {
131   GList *new_list;
132   GList *last;
133
134   new_list = g_list_alloc ();
135   new_list->data = data;
136
137   if (!list)
138     {
139       list = new_list;
140     }
141   else
142     {
143       last = g_list_last (list);
144       g_assert (last != NULL);
145       last->next = new_list;
146       new_list->prev = last;
147     }
148
149   return list;
150 }
151
152 GList*
153 g_list_prepend (GList    *list,
154                 gpointer  data)
155 {
156   GList *new_list;
157
158   new_list = g_list_alloc ();
159   new_list->data = data;
160
161   if (list)
162     {
163       if (list->prev)
164         list->prev->next = new_list;
165       new_list->prev = list->prev;
166       list->prev = new_list;
167     }
168   new_list->next = list;
169
170   return new_list;
171 }
172
173 GList*
174 g_list_insert (GList    *list,
175                gpointer  data,
176                gint      position)
177 {
178   GList *new_list;
179   GList *tmp_list;
180
181   if (position < 0)
182     return g_list_append (list, data);
183   else if (position == 0)
184     return g_list_prepend (list, data);
185
186   tmp_list = g_list_nth (list, position);
187   if (!tmp_list)
188     return g_list_append (list, data);
189
190   new_list = g_list_alloc ();
191   new_list->data = data;
192
193   if (tmp_list->prev)
194     tmp_list->prev->next = new_list;
195   new_list->next = tmp_list;
196   new_list->prev = tmp_list->prev;
197   tmp_list->prev = new_list;
198
199   if (tmp_list == list)
200     list = new_list;
201
202   return list;
203 }
204
205 GList*
206 g_list_remove (GList    *list,
207                gpointer  data)
208 {
209   GList *tmp;
210
211   tmp = list;
212   while (tmp)
213     {
214       if (tmp->data == data)
215         {
216           if (tmp->prev)
217             tmp->prev->next = tmp->next;
218           if (tmp->next)
219             tmp->next->prev = tmp->prev;
220
221           if (list == tmp)
222             list = list->next;
223
224           tmp->next = NULL;
225           tmp->prev = NULL;
226           g_list_free (tmp);
227
228           break;
229         }
230
231       tmp = tmp->next;
232     }
233   return list;
234 }
235
236 GList*
237 g_list_remove_link (GList *list,
238                     GList *link)
239 {
240   if (link)
241     {
242       if (link->prev)
243         link->prev->next = link->next;
244       if (link->next)
245         link->next->prev = link->prev;
246
247       if (link == list)
248         list = list->next;
249
250       link->next = NULL;
251       link->prev = NULL;
252     }
253
254   return list;
255 }
256
257 GList*
258 g_list_reverse (GList *list)
259 {
260   GList *tmp;
261   GList *last;
262
263   last = NULL;
264   while (list)
265     {
266       last = list;
267       tmp = list->next;
268       list->next = list->prev;
269       list->prev = tmp;
270       list = tmp;
271     }
272
273   return last;
274 }
275
276 GList*
277 g_list_nth (GList *list,
278             gint   n)
279 {
280   while ((n-- > 0) && list)
281     list = list->next;
282
283   return list;
284 }
285
286 GList*
287 g_list_find (GList    *list,
288              gpointer  data)
289 {
290   while (list)
291     {
292       if (list->data == data)
293         break;
294       list = list->next;
295     }
296
297   return list;
298 }
299
300 GList*
301 g_list_last (GList *list)
302 {
303   if (list)
304     {
305       while (list->next)
306         list = list->next;
307     }
308
309   return list;
310 }
311
312 GList*
313 g_list_first (GList *list)
314 {
315   if (list)
316     {
317       while (list->prev)
318         list = list->prev;
319     }
320
321   return list;
322 }
323
324 gint
325 g_list_length (GList *list)
326 {
327   gint length;
328
329   length = 0;
330   while (list)
331     {
332       length++;
333       list = list->next;
334     }
335
336   return length;
337 }
338
339 void
340 g_list_foreach (GList    *list,
341                 GFunc     func,
342                 gpointer  user_data)
343 {
344   while (list)
345     {
346       (*func) (list->data, user_data);
347       list = list->next;
348     }
349 }