Main Page | Class List | Directories | File List | Class Members | File Members

garray.c

Go to the documentation of this file.
00001 /* GLIB - Library of useful routines for C programming
00002  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Library General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Library General Public
00015  * License along with this library; if not, write to the
00016  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017  * Boston, MA 02111-1307, USA.
00018  */
00019 
00020 /*
00021  * Modified by the GLib Team and others 1997-1999.  See the AUTHORS
00022  * file for a list of people on the GLib Team.  See the ChangeLog
00023  * files for a list of changes.  These files are distributed with
00024  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
00025  */
00026 
00027 /* 
00028  * MT safe
00029  */
00030 
00031 #include <string.h>
00032 #include "glib.h"
00033 
00034 
00035 #define MIN_ARRAY_SIZE  16
00036 
00037 
00038 typedef struct _GRealArray  GRealArray;
00039 
00040 struct _GRealArray
00041 {
00042   guint8 *data;
00043   guint   len;
00044   guint   alloc;
00045   guint   elt_size;
00046   guint   zero_terminated : 1;
00047   guint   clear : 1;
00048 };
00049 
00050 
00051 static gint g_nearest_pow        (gint        num);
00052 static void g_array_maybe_expand (GRealArray *array,
00053                                   gint        len);
00054 
00055 static GMemChunk *array_mem_chunk = NULL;
00056 G_LOCK_DEFINE_STATIC (array_mem_chunk);
00057 
00058 GArray*
00059 g_array_new (gboolean zero_terminated,
00060              gboolean clear,
00061              guint    elt_size)
00062 {
00063   GRealArray *array;
00064 
00065   G_LOCK (array_mem_chunk);
00066   if (!array_mem_chunk)
00067     array_mem_chunk = g_mem_chunk_new ("array mem chunk",
00068                                        sizeof (GRealArray),
00069                                        1024, G_ALLOC_AND_FREE);
00070 
00071   array = g_chunk_new (GRealArray, array_mem_chunk);
00072   G_UNLOCK (array_mem_chunk);
00073 
00074   array->data            = NULL;
00075   array->len             = 0;
00076   array->alloc           = 0;
00077   array->zero_terminated = (zero_terminated ? 1 : 0);
00078   array->clear           = (clear ? 1 : 0);
00079   array->elt_size        = elt_size;
00080 
00081   return (GArray*) array;
00082 }
00083 
00084 void
00085 g_array_free (GArray  *array,
00086               gboolean free_segment)
00087 {
00088   if (free_segment)
00089     g_free (array->data);
00090 
00091   G_LOCK (array_mem_chunk);
00092   g_mem_chunk_free (array_mem_chunk, array);
00093   G_UNLOCK (array_mem_chunk);
00094 }
00095 
00096 GArray*
00097 g_array_append_vals (GArray       *farray,
00098                      gconstpointer data,
00099                      guint         len)
00100 {
00101   GRealArray *array = (GRealArray*) farray;
00102 
00103   g_array_maybe_expand (array, len);
00104 
00105   memcpy (array->data + array->elt_size * array->len, data, array->elt_size * len);
00106 
00107   array->len += len;
00108 
00109   return farray;
00110 }
00111 
00112 GArray*
00113 g_array_prepend_vals (GArray        *farray,
00114                       gconstpointer  data,
00115                       guint          len)
00116 {
00117   GRealArray *array = (GRealArray*) farray;
00118 
00119   g_array_maybe_expand (array, len);
00120 
00121   g_memmove (array->data + array->elt_size * len, array->data, array->elt_size * array->len);
00122 
00123   memcpy (array->data, data, len * array->elt_size);
00124 
00125   array->len += len;
00126 
00127   return farray;
00128 }
00129 
00130 GArray*
00131 g_array_insert_vals (GArray        *farray,
00132                      guint          index,
00133                      gconstpointer  data,
00134                      guint          len)
00135 {
00136   GRealArray *array = (GRealArray*) farray;
00137 
00138   g_array_maybe_expand (array, len);
00139 
00140   g_memmove (array->data + array->elt_size * (len + index), 
00141              array->data + array->elt_size * index, 
00142              array->elt_size * (array->len - index));
00143 
00144   memcpy (array->data + array->elt_size * index, data, len * array->elt_size);
00145 
00146   array->len += len;
00147 
00148   return farray;
00149 }
00150 
00151 GArray*
00152 g_array_set_size (GArray *farray,
00153                   guint   length)
00154 {
00155   GRealArray *array = (GRealArray*) farray;
00156 
00157   if (array->len < length)
00158     g_array_maybe_expand (array, length - array->len);
00159 
00160   array->len = length;
00161 
00162   return farray;
00163 }
00164 
00165 GArray*
00166 g_array_remove_index (GArray* farray,
00167                       guint index)
00168 {
00169   GRealArray* array = (GRealArray*) farray;
00170 
00171   g_return_val_if_fail (array, NULL);
00172 
00173   g_return_val_if_fail (index < array->len, NULL);
00174 
00175   if (index != array->len - 1)
00176       g_memmove (array->data + array->elt_size * index, 
00177                  array->data + array->elt_size * (index + 1), 
00178                  array->elt_size * (array->len - index - 1));
00179   
00180   if (array->zero_terminated)
00181     memset (array->data + array->elt_size * (array->len - 1), 0, 
00182             array->elt_size);
00183 
00184   array->len -= 1;
00185 
00186   return farray;
00187 }
00188 
00189 GArray*
00190 g_array_remove_index_fast (GArray* farray,
00191                            guint index)
00192 {
00193   GRealArray* array = (GRealArray*) farray;
00194 
00195   g_return_val_if_fail (array, NULL);
00196 
00197   g_return_val_if_fail (index < array->len, NULL);
00198 
00199   if (index != array->len - 1)
00200     g_memmove (array->data + array->elt_size * index, 
00201                array->data + array->elt_size * (array->len - 1), 
00202                array->elt_size);
00203   
00204   if (array->zero_terminated)
00205     memset (array->data + array->elt_size * (array->len - 1), 0, 
00206             array->elt_size);
00207 
00208   array->len -= 1;
00209 
00210   return farray;
00211 }
00212 
00213 static gint
00214 g_nearest_pow (gint num)
00215 {
00216   gint n = 1;
00217 
00218   while (n < num)
00219     n <<= 1;
00220 
00221   return n;
00222 }
00223 
00224 static void
00225 g_array_maybe_expand (GRealArray *array,
00226                       gint        len)
00227 {
00228   guint want_alloc = (array->len + len + array->zero_terminated) * array->elt_size;
00229 
00230   if (want_alloc > array->alloc)
00231     {
00232       guint old_alloc = array->alloc;
00233 
00234       array->alloc = g_nearest_pow (want_alloc);
00235       array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE);
00236 
00237       array->data = g_realloc (array->data, array->alloc);
00238 
00239       if (array->clear || array->zero_terminated)
00240         memset (array->data + old_alloc, 0, array->alloc - old_alloc);
00241     }
00242 }
00243 
00244 /* Pointer Array
00245  */
00246 
00247 typedef struct _GRealPtrArray  GRealPtrArray;
00248 
00249 struct _GRealPtrArray
00250 {
00251   gpointer *pdata;
00252   guint     len;
00253   guint     alloc;
00254 };
00255 
00256 static void g_ptr_array_maybe_expand (GRealPtrArray *array,
00257                                       gint           len);
00258 
00259 static GMemChunk *ptr_array_mem_chunk = NULL;
00260 G_LOCK_DEFINE_STATIC (ptr_array_mem_chunk);
00261 
00262 
00263 GPtrArray*
00264 g_ptr_array_new (void)
00265 {
00266   GRealPtrArray *array;
00267 
00268   G_LOCK (ptr_array_mem_chunk);
00269   if (!ptr_array_mem_chunk)
00270     ptr_array_mem_chunk = g_mem_chunk_new ("array mem chunk",
00271                                            sizeof (GRealPtrArray),
00272                                            1024, G_ALLOC_AND_FREE);
00273 
00274   array = g_chunk_new (GRealPtrArray, ptr_array_mem_chunk);
00275   G_UNLOCK (ptr_array_mem_chunk);
00276 
00277   array->pdata = NULL;
00278   array->len = 0;
00279   array->alloc = 0;
00280 
00281   return (GPtrArray*) array;
00282 }
00283 
00284 void
00285 g_ptr_array_free (GPtrArray   *array,
00286                   gboolean  free_segment)
00287 {
00288   g_return_if_fail (array);
00289 
00290   if (free_segment)
00291     g_free (array->pdata);
00292 
00293   G_LOCK (ptr_array_mem_chunk);
00294   g_mem_chunk_free (ptr_array_mem_chunk, array);
00295   G_UNLOCK (ptr_array_mem_chunk);
00296 }
00297 
00298 static void
00299 g_ptr_array_maybe_expand (GRealPtrArray *array,
00300                           gint        len)
00301 {
00302   guint old_alloc;
00303 
00304   if ((array->len + len) > array->alloc)
00305     {
00306       old_alloc = array->alloc;
00307 
00308       array->alloc = g_nearest_pow (array->len + len);
00309       array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE);
00310       if (array->pdata)
00311         array->pdata = g_realloc (array->pdata, sizeof(gpointer) * array->alloc);
00312       else
00313         array->pdata = g_new0 (gpointer, array->alloc);
00314 
00315       memset (array->pdata + old_alloc, 0, 
00316               sizeof (gpointer) * (array->alloc - old_alloc));
00317     }
00318 }
00319 
00320 void
00321 g_ptr_array_set_size  (GPtrArray   *farray,
00322                        gint          length)
00323 {
00324   GRealPtrArray* array = (GRealPtrArray*) farray;
00325 
00326   g_return_if_fail (array);
00327 
00328   if (length > array->len)
00329     g_ptr_array_maybe_expand (array, (length - array->len));
00330 
00331   array->len = length;
00332 }
00333 
00334 gpointer
00335 g_ptr_array_remove_index (GPtrArray* farray,
00336                           guint index)
00337 {
00338   GRealPtrArray* array = (GRealPtrArray*) farray;
00339   gpointer result;
00340 
00341   g_return_val_if_fail (array, NULL);
00342 
00343   g_return_val_if_fail (index < array->len, NULL);
00344 
00345   result = array->pdata[index];
00346   
00347   if (index != array->len - 1)
00348     g_memmove (array->pdata + index, array->pdata + index + 1, 
00349                sizeof (gpointer) * (array->len - index - 1));
00350   
00351   array->pdata[array->len - 1] = NULL;
00352 
00353   array->len -= 1;
00354 
00355   return result;
00356 }
00357 
00358 gpointer
00359 g_ptr_array_remove_index_fast (GPtrArray* farray,
00360                                guint index)
00361 {
00362   GRealPtrArray* array = (GRealPtrArray*) farray;
00363   gpointer result;
00364 
00365   g_return_val_if_fail (array, NULL);
00366 
00367   g_return_val_if_fail (index < array->len, NULL);
00368 
00369   result = array->pdata[index];
00370   
00371   if (index != array->len - 1)
00372     array->pdata[index] = array->pdata[array->len - 1];
00373 
00374   array->pdata[array->len - 1] = NULL;
00375 
00376   array->len -= 1;
00377 
00378   return result;
00379 }
00380 
00381 gboolean
00382 g_ptr_array_remove (GPtrArray* farray,
00383                     gpointer data)
00384 {
00385   GRealPtrArray* array = (GRealPtrArray*) farray;
00386   int i;
00387 
00388   g_return_val_if_fail (array, FALSE);
00389 
00390   for (i = 0; i < array->len; i += 1)
00391     {
00392       if (array->pdata[i] == data)
00393         {
00394           g_ptr_array_remove_index (farray, i);
00395           return TRUE;
00396         }
00397     }
00398 
00399   return FALSE;
00400 }
00401 
00402 gboolean
00403 g_ptr_array_remove_fast (GPtrArray* farray,
00404                          gpointer data)
00405 {
00406   GRealPtrArray* array = (GRealPtrArray*) farray;
00407   int i;
00408 
00409   g_return_val_if_fail (array, FALSE);
00410 
00411   for (i = 0; i < array->len; i += 1)
00412     {
00413       if (array->pdata[i] == data)
00414         {
00415           g_ptr_array_remove_index_fast (farray, i);
00416           return TRUE;
00417         }
00418     }
00419 
00420   return FALSE;
00421 }
00422 
00423 void
00424 g_ptr_array_add (GPtrArray* farray,
00425                  gpointer data)
00426 {
00427   GRealPtrArray* array = (GRealPtrArray*) farray;
00428 
00429   g_return_if_fail (array);
00430 
00431   g_ptr_array_maybe_expand (array, 1);
00432 
00433   array->pdata[array->len++] = data;
00434 }
00435 
00436 /* Byte arrays
00437  */
00438 
00439 GByteArray* g_byte_array_new      (void)
00440 {
00441   return (GByteArray*) g_array_new (FALSE, FALSE, 1);
00442 }
00443 
00444 void        g_byte_array_free     (GByteArray *array,
00445                                    gboolean    free_segment)
00446 {
00447   g_array_free ((GArray*) array, free_segment);
00448 }
00449 
00450 GByteArray* g_byte_array_append   (GByteArray *array,
00451                                    const guint8 *data,
00452                                    guint       len)
00453 {
00454   g_array_append_vals ((GArray*) array, (guint8*)data, len);
00455 
00456   return array;
00457 }
00458 
00459 GByteArray* g_byte_array_prepend  (GByteArray *array,
00460                                    const guint8 *data,
00461                                    guint       len)
00462 {
00463   g_array_prepend_vals ((GArray*) array, (guint8*)data, len);
00464 
00465   return array;
00466 }
00467 
00468 GByteArray* g_byte_array_set_size (GByteArray *array,
00469                                    guint       length)
00470 {
00471   g_array_set_size ((GArray*) array, length);
00472 
00473   return array;
00474 }
00475 
00476 GByteArray* g_byte_array_remove_index (GByteArray *array,
00477                                        guint index)
00478 {
00479   g_array_remove_index((GArray*) array, index);
00480 
00481   return array;
00482 }
00483 
00484 GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
00485                                                    guint index)
00486 {
00487   g_array_remove_index_fast((GArray*) array, index);
00488 
00489   return array;
00490 }

© sourcejam.com 2005-2008