Batch of new documentation that should be easier to maintain and extend.
[platform/upstream/glib.git] / garray.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #include <string.h>
20 #include "glib.h"
21
22
23 #define MIN_ARRAY_SIZE  16
24
25
26 typedef struct _GRealArray  GRealArray;
27
28 struct _GRealArray
29 {
30   guint8 *data;
31   guint   len;
32   guint   alloc;
33   guint   elt_size;
34   guint   zero_terminated : 1;
35   guint   clear : 1;
36 };
37
38
39 static gint g_nearest_pow        (gint        num);
40 static void g_array_maybe_expand (GRealArray *array,
41                                   gint        len);
42
43
44 static GMemChunk *array_mem_chunk = NULL;
45
46
47 GArray*
48 g_array_new (gboolean zero_terminated,
49              gboolean clear,
50              guint    elt_size)
51 {
52   GRealArray *array;
53
54   if (!array_mem_chunk)
55     array_mem_chunk = g_mem_chunk_new ("array mem chunk",
56                                        sizeof (GRealArray),
57                                        1024, G_ALLOC_AND_FREE);
58
59   array = g_chunk_new (GRealArray, array_mem_chunk);
60
61   array->data            = NULL;
62   array->len             = 0;
63   array->alloc           = 0;
64   array->zero_terminated = (zero_terminated ? 1 : 0);
65   array->clear           = (clear ? 1 : 0);
66   array->elt_size        = elt_size;
67
68   return (GArray*) array;
69 }
70
71 void
72 g_array_free (GArray  *array,
73               gboolean free_segment)
74 {
75   if (free_segment)
76     g_free (array->data);
77
78   g_mem_chunk_free (array_mem_chunk, array);
79 }
80
81 GArray*
82 g_array_append_vals (GArray       *farray,
83                      gconstpointer data,
84                      guint         len)
85 {
86   GRealArray *array = (GRealArray*) farray;
87
88   g_array_maybe_expand (array, len);
89
90   memcpy (array->data + array->elt_size * array->len, data, array->elt_size * len);
91
92   array->len += len;
93
94   return farray;
95 }
96
97 GArray*
98 g_array_prepend_vals (GArray        *farray,
99                       gconstpointer  data,
100                       guint          len)
101 {
102   GRealArray *array = (GRealArray*) farray;
103
104   g_array_maybe_expand (array, len);
105
106   g_memmove (array->data + array->elt_size * len, array->data, array->elt_size * array->len);
107
108   memcpy (array->data, data, len * array->elt_size);
109
110   array->len += len;
111
112   return farray;
113 }
114
115 GArray*
116 g_array_set_size (GArray *farray,
117                   guint   length)
118 {
119   GRealArray *array = (GRealArray*) farray;
120
121   if (array->len < length)
122     g_array_maybe_expand (array, length - array->len);
123
124   array->len = length;
125
126   return farray;
127 }
128
129 GArray*
130 g_array_remove_index (GArray* farray,
131                       guint index)
132 {
133   GRealArray* array = (GRealArray*) farray;
134
135   g_return_val_if_fail (array, NULL);
136
137   g_return_val_if_fail (index >= 0 && index < array->len, NULL);
138
139   if (index != array->len - 1)
140       g_memmove (array->data + array->elt_size * index, 
141                  array->data + array->elt_size * (index + 1), 
142                  array->elt_size * (array->len - index - 1));
143   
144   if (array->zero_terminated)
145     memset (array->data + array->elt_size * (array->len - 1), 0, 
146             array->elt_size);
147
148   array->len -= 1;
149
150   return farray;
151 }
152
153 GArray*
154 g_array_remove_index_fast (GArray* farray,
155                            guint index)
156 {
157   GRealArray* array = (GRealArray*) farray;
158
159   g_return_val_if_fail (array, NULL);
160
161   g_return_val_if_fail (index >= 0 && index < array->len, NULL);
162
163   if (index != array->len - 1)
164     g_memmove (array->data + array->elt_size * index, 
165                array->data + array->elt_size * (array->len - 1), 
166                array->elt_size);
167   
168   if (array->zero_terminated)
169     memset (array->data + array->elt_size * (array->len - 1), 0, 
170             array->elt_size);
171
172   array->len -= 1;
173
174   return farray;
175 }
176
177 static gint
178 g_nearest_pow (gint num)
179 {
180   gint n = 1;
181
182   while (n < num)
183     n <<= 1;
184
185   return n;
186 }
187
188 static void
189 g_array_maybe_expand (GRealArray *array,
190                       gint        len)
191 {
192   guint want_alloc = (array->len + len + array->zero_terminated) * array->elt_size;
193
194   if (want_alloc > array->alloc)
195     {
196       guint old_alloc = array->alloc;
197
198       array->alloc = g_nearest_pow (want_alloc);
199       array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE);
200
201       array->data = g_realloc (array->data, array->alloc);
202
203       if (array->clear || array->zero_terminated)
204         memset (array->data + old_alloc, 0, array->alloc - old_alloc);
205     }
206 }
207
208 /* Pointer Array
209  */
210
211 typedef struct _GRealPtrArray  GRealPtrArray;
212
213 struct _GRealPtrArray
214 {
215   gpointer *pdata;
216   guint     len;
217   guint     alloc;
218 };
219
220 static void g_ptr_array_maybe_expand (GRealPtrArray *array,
221                                       gint           len);
222
223
224 static GMemChunk *ptr_array_mem_chunk = NULL;
225
226
227
228 GPtrArray*
229 g_ptr_array_new (void)
230 {
231   GRealPtrArray *array;
232
233   if (!ptr_array_mem_chunk)
234     ptr_array_mem_chunk = g_mem_chunk_new ("array mem chunk",
235                                            sizeof (GRealPtrArray),
236                                            1024, G_ALLOC_AND_FREE);
237
238   array = g_chunk_new (GRealPtrArray, ptr_array_mem_chunk);
239
240   array->pdata = NULL;
241   array->len = 0;
242   array->alloc = 0;
243
244   return (GPtrArray*) array;
245 }
246
247 void
248 g_ptr_array_free (GPtrArray   *array,
249                   gboolean  free_segment)
250 {
251   g_return_if_fail (array);
252
253   if (free_segment)
254     g_free (array->pdata);
255
256   g_mem_chunk_free (ptr_array_mem_chunk, array);
257 }
258
259 static void
260 g_ptr_array_maybe_expand (GRealPtrArray *array,
261                           gint        len)
262 {
263   guint old_alloc;
264
265   if ((array->len + len) > array->alloc)
266     {
267       old_alloc = array->alloc;
268
269       array->alloc = g_nearest_pow (array->len + len);
270       array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE);
271       if (array->pdata)
272         array->pdata = g_realloc (array->pdata, sizeof(gpointer) * array->alloc);
273       else
274         array->pdata = g_new0 (gpointer, array->alloc);
275
276       memset (array->pdata + old_alloc, 0, array->alloc - old_alloc);
277     }
278 }
279
280 void
281 g_ptr_array_set_size  (GPtrArray   *farray,
282                        gint          length)
283 {
284   GRealPtrArray* array = (GRealPtrArray*) farray;
285
286   g_return_if_fail (array);
287
288   if (length > array->len)
289     g_ptr_array_maybe_expand (array, (length - array->len));
290
291   array->len = length;
292 }
293
294 gpointer
295 g_ptr_array_remove_index (GPtrArray* farray,
296                           guint index)
297 {
298   GRealPtrArray* array = (GRealPtrArray*) farray;
299   gpointer result;
300
301   g_return_val_if_fail (array, NULL);
302
303   g_return_val_if_fail (index >= 0 && index < array->len, NULL);
304
305   result = array->pdata[index];
306   
307   if (index != array->len - 1)
308     g_memmove (array->pdata + index, array->pdata + index + 1, 
309                array->len - index - 1);
310   
311   array->pdata[array->len - 1] = NULL;
312
313   array->len -= 1;
314
315   return result;
316 }
317
318 gpointer
319 g_ptr_array_remove_index_fast (GPtrArray* farray,
320                                guint index)
321 {
322   GRealPtrArray* array = (GRealPtrArray*) farray;
323   gpointer result;
324
325   g_return_val_if_fail (array, NULL);
326
327   g_return_val_if_fail (index >= 0 && index < array->len, NULL);
328
329   result = array->pdata[index];
330   
331   if (index != array->len - 1)
332     array->pdata[index] = array->pdata[array->len - 1];
333
334   array->pdata[array->len - 1] = NULL;
335
336   array->len -= 1;
337
338   return result;
339 }
340
341 gboolean
342 g_ptr_array_remove (GPtrArray* farray,
343                     gpointer data)
344 {
345   GRealPtrArray* array = (GRealPtrArray*) farray;
346   int i;
347
348   g_return_val_if_fail (array, FALSE);
349
350   for (i = 0; i < array->len; i += 1)
351     {
352       if (array->pdata[i] == data)
353         {
354           g_ptr_array_remove_index (farray, i);
355           return TRUE;
356         }
357     }
358
359   return FALSE;
360 }
361
362 gboolean
363 g_ptr_array_remove_fast (GPtrArray* farray,
364                          gpointer data)
365 {
366   GRealPtrArray* array = (GRealPtrArray*) farray;
367   int i;
368
369   g_return_val_if_fail (array, FALSE);
370
371   for (i = 0; i < array->len; i += 1)
372     {
373       if (array->pdata[i] == data)
374         {
375           g_ptr_array_remove_index_fast (farray, i);
376           return TRUE;
377         }
378     }
379
380   return FALSE;
381 }
382
383 void
384 g_ptr_array_add (GPtrArray* farray,
385                  gpointer data)
386 {
387   GRealPtrArray* array = (GRealPtrArray*) farray;
388
389   g_return_if_fail (array);
390
391   g_ptr_array_maybe_expand (array, 1);
392
393   array->pdata[array->len++] = data;
394 }
395
396 /* Byte arrays
397  */
398
399 GByteArray* g_byte_array_new      (void)
400 {
401   return (GByteArray*) g_array_new (FALSE, FALSE, 1);
402 }
403
404 void        g_byte_array_free     (GByteArray *array,
405                                    gboolean    free_segment)
406 {
407   g_array_free ((GArray*) array, free_segment);
408 }
409
410 GByteArray* g_byte_array_append   (GByteArray *array,
411                                    const guint8 *data,
412                                    guint       len)
413 {
414   g_array_append_vals ((GArray*) array, (guint8*)data, len);
415
416   return array;
417 }
418
419 GByteArray* g_byte_array_prepend  (GByteArray *array,
420                                    const guint8 *data,
421                                    guint       len)
422 {
423   g_array_prepend_vals ((GArray*) array, (guint8*)data, len);
424
425   return array;
426 }
427
428 GByteArray* g_byte_array_set_size (GByteArray *array,
429                                    guint       length)
430 {
431   g_array_set_size ((GArray*) array, length);
432
433   return array;
434 }
435
436 GByteArray* g_byte_array_remove_index (GByteArray *array,
437                                        guint index)
438 {
439   g_array_remove_index((GArray*) array, index);
440
441   return array;
442 }
443
444 GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
445                                                    guint index)
446 {
447   g_array_remove_index_fast((GArray*) array, index);
448
449   return array;
450 }