[xbuild] Update man page with info about FrameworkList.xml
[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         gint capacity;
43 } GArrayPriv;
44
45 static void
46 ensure_capacity (GArrayPriv *priv,
47                  int capacity)
48 {
49         int new_capacity = MAX (priv->capacity, INITIAL_CAPACITY);
50
51         if (capacity < priv->capacity)
52                 return;
53
54         while (new_capacity < capacity) {
55                 new_capacity <<= 1;
56         }
57         capacity = new_capacity;
58         priv->array.data = (gchar*)g_realloc (priv->array.data, element_length (priv, capacity));
59
60         if (priv->clear_) {
61                 memset (element_offset (priv, priv->capacity),
62                         0,
63                         element_length (priv, capacity - priv->capacity));
64         }
65         priv->capacity = capacity;
66 }
67
68 GArray *
69 g_array_new (gboolean zero_terminated,
70              gboolean clear_,
71              guint element_size)
72 {
73         GArrayPriv *rv = g_new0 (GArrayPriv, 1);
74         rv->zero_terminated = zero_terminated;
75         rv->clear_ = clear_;
76         rv->element_size = element_size;
77
78         ensure_capacity (rv, INITIAL_CAPACITY);
79
80         return (GArray*)rv;
81 }
82
83 gchar*
84 g_array_free (GArray *array,
85               gboolean free_segment)
86 {
87         gchar* rv = NULL;
88
89         g_return_val_if_fail (array != NULL, NULL);
90
91         if (free_segment)
92                 g_free (array->data);
93         else
94                 rv = array->data;
95
96         g_free (array);
97
98         return rv;
99 }
100
101 GArray *
102 g_array_append_vals (GArray *array,
103                      gconstpointer data,
104                      guint len)
105 {
106         GArrayPriv *priv = (GArrayPriv*)array;
107
108         g_return_val_if_fail (array != NULL, NULL);
109
110         ensure_capacity (priv, priv->array.len + len + (priv->zero_terminated ? 1 : 0));
111   
112         memmove (element_offset (priv, priv->array.len),
113                  data,
114                  element_length (priv, len));
115
116         priv->array.len += len;
117
118         if (priv->zero_terminated) {
119                 memset (element_offset (priv, priv->array.len),
120                         0,
121                         priv->element_size);
122         }
123
124         return array;
125 }
126
127 GArray*
128 g_array_insert_vals (GArray *array,
129                      guint index_,
130                      gconstpointer data,
131                      guint len)
132 {
133         GArrayPriv *priv = (GArrayPriv*)array;
134         guint extra = (priv->zero_terminated ? 1 : 0);
135
136         g_return_val_if_fail (array != NULL, NULL);
137
138         ensure_capacity (priv, array->len + len + extra);
139   
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_));
144
145         /* then copy the new elements into the array */
146         memmove (element_offset (priv, index_),
147                  data,
148                  element_length (priv, len));
149
150         array->len += len;
151
152         if (priv->zero_terminated) {
153                 memset (element_offset (priv, priv->array.len),
154                         0,
155                         priv->element_size);
156         }
157
158         return array;
159 }
160
161 GArray*
162 g_array_remove_index (GArray *array,
163                       guint index_)
164 {
165         GArrayPriv *priv = (GArrayPriv*)array;
166
167         g_return_val_if_fail (array != NULL, NULL);
168
169         memmove (element_offset (priv, index_),
170                  element_offset (priv, index_ + 1),
171                  element_length (priv, array->len - index_));
172
173         array->len --;
174
175         if (priv->zero_terminated) {
176                 memset (element_offset (priv, priv->array.len),
177                         0,
178                         priv->element_size);
179         }
180
181         return array;
182 }
183
184 GArray*
185 g_array_remove_index_fast (GArray *array,
186                       guint index_)
187 {
188         GArrayPriv *priv = (GArrayPriv*)array;
189
190         g_return_val_if_fail (array != NULL, NULL);
191
192         memmove (element_offset (priv, index_),
193                  element_offset (priv, array->len - 1),
194                  element_length (priv, 1));
195
196         array->len --;
197
198         if (priv->zero_terminated) {
199                 memset (element_offset (priv, priv->array.len),
200                         0,
201                         priv->element_size);
202         }
203
204         return array;
205 }
206