2006-08-17 Aaron Bockover <abockover@novell.com>
[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 #define _GNU_SOURCE
30 #include <stdlib.h>
31 #include <glib.h>
32
33 #define MAX(a,b) ((a) > (b) ? (a) : (b))
34
35 typedef struct _GPtrArrayPriv {
36         gpointer *pdata;
37         guint len;
38         guint size;
39 } GPtrArrayPriv;
40
41 static void 
42 g_ptr_array_grow(GPtrArrayPriv *array, guint length)
43 {
44         gint new_length = array->len + length;
45
46         g_return_if_fail(array != NULL);
47
48         if(new_length <= array->size) {
49                 return;
50         }
51
52         array->size = 1;
53
54         while(array->size < new_length) {
55                 array->size <<= 1;
56         }
57
58         array->size = MAX(array->size, 16);
59         array->pdata = g_realloc(array->pdata, array->size * sizeof(gpointer));
60 }
61
62 GPtrArray *
63 g_ptr_array_new()
64 {
65         return g_ptr_array_sized_new(0);
66 }
67
68 GPtrArray *
69 g_ptr_array_sized_new(guint reserved_size)
70 {
71         GPtrArrayPriv *array = g_new0(GPtrArrayPriv, 1);
72
73         array->pdata = NULL;
74         array->len = 0;
75         array->size = 0;
76
77         if(reserved_size > 0) {
78                 g_ptr_array_grow(array, reserved_size);
79         }
80
81         return (GPtrArray *)array;
82 }
83
84 gpointer *
85 g_ptr_array_free(GPtrArray *array, gboolean free_seg)
86 {
87         gpointer *data = NULL;
88         
89         g_return_val_if_fail(array != NULL, NULL);
90
91         if(free_seg) {
92                 g_free(array->pdata);
93         } else {
94                 data = array->pdata;
95         }
96
97         g_free(array);
98         
99         return data;
100 }
101
102 void
103 g_ptr_array_set_size(GPtrArray *array, gint length)
104 {
105         g_return_if_fail(array != NULL);
106
107         if(length > array->len) {
108                 g_ptr_array_grow((GPtrArrayPriv *)array, length);
109                 memset(array->pdata + array->len, 0, (length - array->len) 
110                         * sizeof(gpointer));
111         }
112
113         array->len = length;
114 }
115
116 void
117 g_ptr_array_add(GPtrArray *array, gpointer data)
118 {
119         g_return_if_fail(array != NULL);
120         g_ptr_array_grow((GPtrArrayPriv *)array, 1);
121         array->pdata[array->len++] = data;
122 }
123
124 gpointer
125 g_ptr_array_remove_index(GPtrArray *array, guint index)
126 {
127         gpointer removed_node;
128         
129         g_return_val_if_fail(array != NULL, NULL);
130         g_return_val_if_fail(index >= 0 || index < array->len, NULL);
131
132         removed_node = array->pdata[index];
133
134         if(index != array->len - 1) {
135                 g_memmove(array->pdata + index, array->pdata + index + 1,
136                         (array->len - index - 1) * sizeof(gpointer));
137         }
138         
139         array->len -= 1;
140 //      array->pdata[array->len - 1] = NULL;
141
142         return removed_node;
143 }
144
145 gboolean
146 g_ptr_array_remove(GPtrArray *array, gpointer data)
147 {
148         guint i;
149
150         g_return_val_if_fail(array != NULL, FALSE);
151
152         for(i = 0; i < array->len; i++) {
153                 if(array->pdata[i] == data) {
154                         g_ptr_array_remove_index(array, i);
155                         return TRUE;
156                 }
157         }
158
159         return FALSE;
160 }
161
162 void 
163 g_ptr_array_foreach(GPtrArray *array, GFunc func, gpointer user_data)
164 {
165         gint i;
166
167         for(i = 0; i < array->len; i++) {
168                 func(g_ptr_array_index(array, i), user_data);
169         }
170 }
171