2010-06-21 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / eglib / src / garray.c
blobdadb6caa1834cbb370ee3fb4ae02cc6f6a6a2085
1 /*
2 * Arrays
4 * Author:
5 * Chris Toshok (toshok@novell.com)
7 * (C) 2006 Novell, Inc.
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:
17 * The above copyright notice and this permission notice shall be
18 * included in all copies or substantial portions of the Software.
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.
29 #include <stdlib.h>
30 #include <glib.h>
32 #define INITIAL_CAPACITY 16
34 #define element_offset(p,i) ((p)->array.data + (i) * (p)->element_size)
35 #define element_length(p,i) ((i) * (p)->element_size)
37 typedef struct {
38 GArray array;
39 gboolean clear_;
40 gboolean element_size;
41 gboolean zero_terminated;
42 gint capacity;
43 } GArrayPriv;
45 static void
46 ensure_capacity (GArrayPriv *priv,
47 int capacity)
49 int new_capacity = MAX (priv->capacity, INITIAL_CAPACITY);
51 if (capacity < priv->capacity)
52 return;
54 while (new_capacity < capacity) {
55 new_capacity <<= 1;
57 capacity = new_capacity;
58 priv->array.data = (gchar*)g_realloc (priv->array.data, element_length (priv, capacity));
60 if (priv->clear_) {
61 memset (element_offset (priv, priv->capacity),
63 element_length (priv, capacity - priv->capacity));
65 priv->capacity = capacity;
68 GArray *
69 g_array_new (gboolean zero_terminated,
70 gboolean clear_,
71 guint element_size)
73 GArrayPriv *rv = g_new0 (GArrayPriv, 1);
74 rv->zero_terminated = zero_terminated;
75 rv->clear_ = clear_;
76 rv->element_size = element_size;
78 ensure_capacity (rv, INITIAL_CAPACITY);
80 return (GArray*)rv;
83 gchar*
84 g_array_free (GArray *array,
85 gboolean free_segment)
87 gchar* rv = NULL;
89 g_return_val_if_fail (array != NULL, NULL);
91 if (free_segment)
92 g_free (array->data);
93 else
94 rv = array->data;
96 g_free (array);
98 return rv;
101 GArray *
102 g_array_append_vals (GArray *array,
103 gconstpointer data,
104 guint len)
106 GArrayPriv *priv = (GArrayPriv*)array;
108 g_return_val_if_fail (array != NULL, NULL);
110 ensure_capacity (priv, priv->array.len + len + (priv->zero_terminated ? 1 : 0));
112 memmove (element_offset (priv, priv->array.len),
113 data,
114 element_length (priv, len));
116 priv->array.len += len;
118 if (priv->zero_terminated) {
119 memset (element_offset (priv, priv->array.len),
121 priv->element_size);
124 return array;
127 GArray*
128 g_array_insert_vals (GArray *array,
129 guint index_,
130 gconstpointer data,
131 guint len)
133 GArrayPriv *priv = (GArrayPriv*)array;
134 guint extra = (priv->zero_terminated ? 1 : 0);
136 g_return_val_if_fail (array != NULL, NULL);
138 ensure_capacity (priv, array->len + len + extra);
140 /* first move the existing elements out of the way */
141 memmove (element_offset (priv, index_ + len),
142 element_offset (priv, index_),
143 element_length (priv, array->len - index_));
145 /* then copy the new elements into the array */
146 memmove (element_offset (priv, index_),
147 data,
148 element_length (priv, len));
150 array->len += len;
152 if (priv->zero_terminated) {
153 memset (element_offset (priv, priv->array.len),
155 priv->element_size);
158 return array;
161 GArray*
162 g_array_remove_index (GArray *array,
163 guint index_)
165 GArrayPriv *priv = (GArrayPriv*)array;
167 g_return_val_if_fail (array != NULL, NULL);
169 memmove (element_offset (priv, index_),
170 element_offset (priv, index_ + 1),
171 element_length (priv, array->len - index_));
173 array->len --;
175 if (priv->zero_terminated) {
176 memset (element_offset (priv, priv->array.len),
178 priv->element_size);
181 return array;
184 GArray*
185 g_array_remove_index_fast (GArray *array,
186 guint index_)
188 GArrayPriv *priv = (GArrayPriv*)array;
190 g_return_val_if_fail (array != NULL, NULL);
192 memmove (element_offset (priv, index_),
193 element_offset (priv, array->len - 1),
194 element_length (priv, 1));
196 array->len --;
198 if (priv->zero_terminated) {
199 memset (element_offset (priv, priv->array.len),
201 priv->element_size);
204 return array;