[msvc] Update csproj files
[mono.git] / eglib / src / garray.c
1 /*
2  * Arrays
3  *
4  * Author:
5  *   Chris Toshok (toshok@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 #define INITIAL_CAPACITY 16
33
34 #define element_offset(p,i) ((p)->array.data + (i) * (p)->element_size)
35 #define element_length(p,i) ((i) * (p)->element_size)
36
37 typedef struct {
38         GArray array;
39         gboolean clear_;
40         guint element_size;
41         gboolean zero_terminated;
42         guint capacity;
43 } GArrayPriv;
44
45 static void
46 ensure_capacity (GArrayPriv *priv, guint capacity)
47 {
48         guint new_capacity;
49         
50         if (capacity <= priv->capacity)
51                 return;
52         
53         new_capacity = (capacity + 63) & ~63;
54         
55         priv->array.data = g_realloc (priv->array.data, element_length (priv, new_capacity));
56         
57         if (priv->clear_) {
58                 memset (element_offset (priv, priv->capacity),
59                         0,
60                         element_length (priv, new_capacity - priv->capacity));
61         }
62         
63         priv->capacity = new_capacity;
64 }
65
66 GArray *
67 g_array_new (gboolean zero_terminated,
68              gboolean clear_,
69              guint element_size)
70 {
71         GArrayPriv *rv = g_new0 (GArrayPriv, 1);
72         rv->zero_terminated = zero_terminated;
73         rv->clear_ = clear_;
74         rv->element_size = element_size;
75
76         ensure_capacity (rv, INITIAL_CAPACITY);
77
78         return (GArray*)rv;
79 }
80
81 GArray *
82 g_array_sized_new (gboolean zero_terminated,
83              gboolean clear_,
84              guint element_size,
85                  guint reserved_size)
86 {
87         GArrayPriv *rv = g_new0 (GArrayPriv, 1);
88         rv->zero_terminated = zero_terminated;
89         rv->clear_ = clear_;
90         rv->element_size = element_size;
91
92         ensure_capacity (rv, reserved_size);
93
94         return (GArray*)rv;
95 }
96
97 gchar*
98 g_array_free (GArray *array,
99               gboolean free_segment)
100 {
101         gchar* rv = NULL;
102
103         g_return_val_if_fail (array != NULL, NULL);
104
105         if (free_segment)
106                 g_free (array->data);
107         else
108                 rv = array->data;
109
110         g_free (array);
111
112         return rv;
113 }
114
115 GArray *
116 g_array_append_vals (GArray *array,
117                      gconstpointer data,
118                      guint len)
119 {
120         GArrayPriv *priv = (GArrayPriv*)array;
121
122         g_return_val_if_fail (array != NULL, NULL);
123
124         ensure_capacity (priv, priv->array.len + len + (priv->zero_terminated ? 1 : 0));
125   
126         memmove (element_offset (priv, priv->array.len),
127                  data,
128                  element_length (priv, len));
129
130         priv->array.len += len;
131
132         if (priv->zero_terminated) {
133                 memset (element_offset (priv, priv->array.len),
134                         0,
135                         priv->element_size);
136         }
137
138         return array;
139 }
140
141 GArray*
142 g_array_insert_vals (GArray *array,
143                      guint index_,
144                      gconstpointer data,
145                      guint len)
146 {
147         GArrayPriv *priv = (GArrayPriv*)array;
148         guint extra = (priv->zero_terminated ? 1 : 0);
149
150         g_return_val_if_fail (array != NULL, NULL);
151
152         ensure_capacity (priv, array->len + len + extra);
153   
154         /* first move the existing elements out of the way */
155         memmove (element_offset (priv, index_ + len),
156                  element_offset (priv, index_),
157                  element_length (priv, array->len - index_));
158
159         /* then copy the new elements into the array */
160         memmove (element_offset (priv, index_),
161                  data,
162                  element_length (priv, len));
163
164         array->len += len;
165
166         if (priv->zero_terminated) {
167                 memset (element_offset (priv, priv->array.len),
168                         0,
169                         priv->element_size);
170         }
171
172         return array;
173 }
174
175 GArray*
176 g_array_remove_index (GArray *array,
177                       guint index_)
178 {
179         GArrayPriv *priv = (GArrayPriv*)array;
180
181         g_return_val_if_fail (array != NULL, NULL);
182
183         memmove (element_offset (priv, index_),
184                  element_offset (priv, index_ + 1),
185                  element_length (priv, array->len - index_));
186
187         array->len --;
188
189         if (priv->zero_terminated) {
190                 memset (element_offset (priv, priv->array.len),
191                         0,
192                         priv->element_size);
193         }
194
195         return array;
196 }
197
198 GArray*
199 g_array_remove_index_fast (GArray *array,
200                       guint index_)
201 {
202         GArrayPriv *priv = (GArrayPriv*)array;
203
204         g_return_val_if_fail (array != NULL, NULL);
205
206         memmove (element_offset (priv, index_),
207                  element_offset (priv, array->len - 1),
208                  element_length (priv, 1));
209
210         array->len --;
211
212         if (priv->zero_terminated) {
213                 memset (element_offset (priv, priv->array.len),
214                         0,
215                         priv->element_size);
216         }
217
218         return array;
219 }
220
221 void
222 g_array_set_size (GArray *array, gint length)
223 {
224         GArrayPriv *priv = (GArrayPriv*)array;
225
226         g_return_if_fail (array != NULL);
227         g_return_if_fail (length >= 0);
228
229         if (length == priv->capacity)
230                 return; // nothing to be done
231
232         if (length > priv->capacity) {
233                 // grow the array
234                 ensure_capacity (priv, length);
235         }
236
237         array->len = length;
238 }