New tests.
[mono.git] / eglib / src / gptrarray.c
1 /*
2  * Pointer Array
3  *
4  * Author:
5  *   Aaron Bockover (abockover@novell.com)
6  *
7  * (C) 2006 Novell, Inc.
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining
10  * a copy of this software and associated documentation files (the
11  * "Software"), to deal in the Software without restriction, including
12  * without limitation the rights to use, copy, modify, merge, publish,
13  * distribute, sublicense, and/or sell copies of the Software, and to
14  * permit persons to whom the Software is furnished to do so, subject to
15  * the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be
18  * included in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27  */
28  
29 #include <stdlib.h>
30 #include <glib.h>
31
32 typedef struct _GPtrArrayPriv {
33         gpointer *pdata;
34         guint len;
35         guint size;
36 } GPtrArrayPriv;
37
38 static void 
39 g_ptr_array_grow(GPtrArrayPriv *array, guint length)
40 {
41         guint new_length = array->len + length;
42
43         g_return_if_fail(array != NULL);
44
45         if(new_length <= array->size) {
46                 return;
47         }
48
49         array->size = 1;
50
51         while(array->size < new_length) {
52                 array->size <<= 1;
53         }
54
55         array->size = MAX(array->size, 16);
56         array->pdata = g_realloc(array->pdata, array->size * sizeof(gpointer));
57 }
58
59 GPtrArray *
60 g_ptr_array_new()
61 {
62         return g_ptr_array_sized_new(0);
63 }
64
65 GPtrArray *
66 g_ptr_array_sized_new(guint reserved_size)
67 {
68         GPtrArrayPriv *array = g_new0(GPtrArrayPriv, 1);
69
70         array->pdata = NULL;
71         array->len = 0;
72         array->size = 0;
73
74         if(reserved_size > 0) {
75                 g_ptr_array_grow(array, reserved_size);
76         }
77
78         return (GPtrArray *)array;
79 }
80
81 gpointer *
82 g_ptr_array_free(GPtrArray *array, gboolean free_seg)
83 {
84         gpointer *data = NULL;
85         
86         g_return_val_if_fail(array != NULL, NULL);
87
88         if(free_seg) {
89                 g_free(array->pdata);
90         } else {
91                 data = array->pdata;
92         }
93
94         g_free(array);
95         
96         return data;
97 }
98
99 void
100 g_ptr_array_set_size(GPtrArray *array, gint length)
101 {
102         g_return_if_fail(array != NULL);
103
104         if((size_t)length > array->len) {
105                 g_ptr_array_grow((GPtrArrayPriv *)array, length);
106                 memset(array->pdata + array->len, 0, (length - array->len) 
107                         * sizeof(gpointer));
108         }
109
110         array->len = length;
111 }
112
113 void
114 g_ptr_array_add(GPtrArray *array, gpointer data)
115 {
116         g_return_if_fail(array != NULL);
117         g_ptr_array_grow((GPtrArrayPriv *)array, 1);
118         array->pdata[array->len++] = data;
119 }
120
121 gpointer
122 g_ptr_array_remove_index(GPtrArray *array, guint index)
123 {
124         gpointer removed_node;
125         
126         g_return_val_if_fail(array != NULL, NULL);
127         g_return_val_if_fail(index >= 0 || index < array->len, NULL);
128
129         removed_node = array->pdata[index];
130
131         if(index != array->len - 1) {
132                 g_memmove(array->pdata + index, array->pdata + index + 1,
133                         (array->len - index - 1) * sizeof(gpointer));
134         }
135         
136         array->len--;
137         array->pdata[array->len] = NULL;
138
139         return removed_node;
140 }
141
142 gpointer
143 g_ptr_array_remove_index_fast(GPtrArray *array, guint index)
144 {
145         gpointer removed_node;
146
147         g_return_val_if_fail(array != NULL, NULL);
148         g_return_val_if_fail(index >= 0 || index < array->len, NULL);
149
150         removed_node = array->pdata[index];
151
152         if(index != array->len - 1) {
153                 g_memmove(array->pdata + index, array->pdata + array->len - 1,
154                         sizeof(gpointer));
155         }
156
157         array->len--;
158         array->pdata[array->len] = NULL;
159
160         return removed_node;
161 }
162
163 gboolean
164 g_ptr_array_remove(GPtrArray *array, gpointer data)
165 {
166         guint i;
167
168         g_return_val_if_fail(array != NULL, FALSE);
169
170         for(i = 0; i < array->len; i++) {
171                 if(array->pdata[i] == data) {
172                         g_ptr_array_remove_index(array, i);
173                         return TRUE;
174                 }
175         }
176
177         return FALSE;
178 }
179
180 gboolean
181 g_ptr_array_remove_fast(GPtrArray *array, gpointer data)
182 {
183         guint i;
184
185         g_return_val_if_fail(array != NULL, FALSE);
186
187         for(i = 0; i < array->len; i++) {
188                 if(array->pdata[i] == data) {
189                         array->len--;
190                         if (array->len > 0)
191                                 array->pdata [i] = array->pdata [array->len];
192                         else
193                                 array->pdata [i] = NULL;
194                         return TRUE;
195                 }
196         }
197
198         return FALSE;
199 }
200
201 void 
202 g_ptr_array_foreach(GPtrArray *array, GFunc func, gpointer user_data)
203 {
204         guint i;
205
206         for(i = 0; i < array->len; i++) {
207                 func(g_ptr_array_index(array, i), user_data);
208         }
209 }
210
211 void
212 g_ptr_array_sort(GPtrArray *array, GCompareFunc compare_func)
213 {
214         g_return_if_fail(array != NULL);
215         qsort(array->pdata, array->len, sizeof(gpointer), compare_func);
216 }
217
218 void
219 g_ptr_array_sort_with_data(GPtrArray *array, GCompareDataFunc compare_func, 
220         gpointer user_data)
221 {
222 }
223
224
225