os/ossrv/glib/glib/garray.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /* GLIB - Library of useful routines for C programming
     2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
     3  * Portions copyright (c) 2006-2009 Nokia Corporation.  All rights reserved.
     4  *
     5  * This library is free software; you can redistribute it and/or
     6  * modify it under the terms of the GNU Lesser General Public
     7  * License as published by the Free Software Foundation; either
     8  * version 2 of the License, or (at your option) any later version.
     9  *
    10  * This library is distributed in the hope that it will be useful,
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13  * Lesser General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU Lesser General Public
    16  * License along with this library; if not, write to the
    17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    18  * Boston, MA 02111-1307, USA.
    19  */
    20 
    21 /*
    22  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
    23  * file for a list of people on the GLib Team.  See the ChangeLog
    24  * files for a list of changes.  These files are distributed with
    25  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
    26  */
    27 
    28 /* 
    29  * MT safe
    30  */
    31 
    32 #include "config.h"
    33 
    34 #include <string.h>
    35 #include <stdlib.h>
    36 
    37 #include "garray.h"
    38 
    39 #include "gmem.h"
    40 #include "gthread.h"
    41 #include "gmessages.h"
    42 #include "gqsort.h"
    43 
    44 #include "galias.h"
    45 
    46 #ifdef __SYMBIAN32__
    47 #define g_mem_gc_friendly (*_g_mem_gc_friendly())
    48 #endif /* __SYMBIAN32__ */
    49 
    50 #define MIN_ARRAY_SIZE  16
    51 
    52 typedef struct _GRealArray  GRealArray;
    53 
    54 struct _GRealArray
    55 {
    56   guint8 *data;
    57   guint   len;
    58   guint   alloc;
    59   guint   elt_size;
    60   guint   zero_terminated : 1;
    61   guint   clear : 1;
    62 };
    63 
    64 #define g_array_elt_len(array,i) ((array)->elt_size * (i))
    65 #define g_array_elt_pos(array,i) ((array)->data + g_array_elt_len((array),(i)))
    66 #define g_array_elt_zero(array, pos, len) 				\
    67   (memset (g_array_elt_pos ((array), pos), 0,  g_array_elt_len ((array), len)))
    68 #define g_array_zero_terminate(array) G_STMT_START{			\
    69   if ((array)->zero_terminated)						\
    70     g_array_elt_zero ((array), (array)->len, 1);			\
    71 }G_STMT_END
    72 
    73 static gint g_nearest_pow        (gint        num) G_GNUC_CONST;
    74 static void g_array_maybe_expand (GRealArray *array,
    75 				  gint        len);
    76 
    77 EXPORT_C GArray*
    78 g_array_new (gboolean zero_terminated,
    79 	     gboolean clear,
    80 	     guint    elt_size)
    81 {
    82   return (GArray*) g_array_sized_new (zero_terminated, clear, elt_size, 0);
    83 }
    84 
    85 EXPORT_C GArray* g_array_sized_new (gboolean zero_terminated,
    86 			   gboolean clear,
    87 			   guint    elt_size,
    88 			   guint    reserved_size)
    89 {
    90   GRealArray *array = g_slice_new (GRealArray);
    91 
    92   array->data            = NULL;
    93   array->len             = 0;
    94   array->alloc           = 0;
    95   array->zero_terminated = (zero_terminated ? 1 : 0);
    96   array->clear           = (clear ? 1 : 0);
    97   array->elt_size        = elt_size;
    98 
    99   if (array->zero_terminated || reserved_size != 0)
   100     {
   101       g_array_maybe_expand (array, reserved_size);
   102       g_array_zero_terminate(array);
   103     }
   104 
   105   return (GArray*) array;
   106 }
   107 
   108 EXPORT_C gchar*
   109 g_array_free (GArray   *array,
   110 	      gboolean  free_segment)
   111 {
   112   gchar* segment;
   113 
   114   g_return_val_if_fail (array, NULL);
   115 
   116   if (free_segment)
   117     {
   118       g_free (array->data);
   119       segment = NULL;
   120     }
   121   else
   122     segment = array->data;
   123 
   124   g_slice_free1 (sizeof (GRealArray), array);
   125 
   126   return segment;
   127 }
   128 
   129 EXPORT_C GArray*
   130 g_array_append_vals (GArray       *farray,
   131 		     gconstpointer data,
   132 		     guint         len)
   133 {
   134   GRealArray *array = (GRealArray*) farray;
   135 
   136   g_array_maybe_expand (array, len);
   137 
   138   memcpy (g_array_elt_pos (array, array->len), data, 
   139 	  g_array_elt_len (array, len));
   140 
   141   array->len += len;
   142 
   143   g_array_zero_terminate (array);
   144 
   145   return farray;
   146 }
   147 
   148 EXPORT_C GArray*
   149 g_array_prepend_vals (GArray        *farray,
   150 		      gconstpointer  data,
   151 		      guint          len)
   152 {
   153   GRealArray *array = (GRealArray*) farray;
   154 
   155   g_array_maybe_expand (array, len);
   156 
   157   g_memmove (g_array_elt_pos (array, len), g_array_elt_pos (array, 0), 
   158 	     g_array_elt_len (array, array->len));
   159 
   160   memcpy (g_array_elt_pos (array, 0), data, g_array_elt_len (array, len));
   161 
   162   array->len += len;
   163 
   164   g_array_zero_terminate (array);
   165 
   166   return farray;
   167 }
   168 
   169 EXPORT_C GArray*
   170 g_array_insert_vals (GArray        *farray,
   171 		     guint          index_,
   172 		     gconstpointer  data,
   173 		     guint          len)
   174 {
   175   GRealArray *array = (GRealArray*) farray;
   176 
   177   g_array_maybe_expand (array, len);
   178 
   179   g_memmove (g_array_elt_pos (array, len + index_), 
   180 	     g_array_elt_pos (array, index_), 
   181 	     g_array_elt_len (array, array->len - index_));
   182 
   183   memcpy (g_array_elt_pos (array, index_), data, g_array_elt_len (array, len));
   184 
   185   array->len += len;
   186 
   187   g_array_zero_terminate (array);
   188 
   189   return farray;
   190 }
   191 
   192 EXPORT_C GArray*
   193 g_array_set_size (GArray *farray,
   194 		  guint   length)
   195 {
   196   GRealArray *array = (GRealArray*) farray;
   197   if (length > array->len)
   198     {
   199       g_array_maybe_expand (array, length - array->len);
   200       
   201       if (array->clear)
   202 	g_array_elt_zero (array, array->len, length - array->len);
   203     }
   204   else if (G_UNLIKELY (g_mem_gc_friendly) && length < array->len)
   205     g_array_elt_zero (array, length, array->len - length);
   206   
   207   array->len = length;
   208   
   209   g_array_zero_terminate (array);
   210   
   211   return farray;
   212 }
   213 
   214 EXPORT_C GArray*
   215 g_array_remove_index (GArray *farray,
   216 		      guint   index_)
   217 {
   218   GRealArray* array = (GRealArray*) farray;
   219 
   220   g_return_val_if_fail (array, NULL);
   221 
   222   g_return_val_if_fail (index_ < array->len, NULL);
   223 
   224   if (index_ != array->len - 1)
   225     g_memmove (g_array_elt_pos (array, index_),
   226 	       g_array_elt_pos (array, index_ + 1),
   227 	       g_array_elt_len (array, array->len - index_ - 1));
   228   
   229   array->len -= 1;
   230 
   231   if (G_UNLIKELY (g_mem_gc_friendly))
   232     g_array_elt_zero (array, array->len, 1);
   233   else
   234     g_array_zero_terminate (array);
   235 
   236   return farray;
   237 }
   238 
   239 EXPORT_C GArray*
   240 g_array_remove_index_fast (GArray *farray,
   241 			   guint   index_)
   242 {
   243   GRealArray* array = (GRealArray*) farray;
   244 
   245   g_return_val_if_fail (array, NULL);
   246 
   247   g_return_val_if_fail (index_ < array->len, NULL);
   248 
   249   if (index_ != array->len - 1)
   250     memcpy (g_array_elt_pos (array, index_), 
   251 	    g_array_elt_pos (array, array->len - 1),
   252 	    g_array_elt_len (array, 1));
   253   
   254   array->len -= 1;
   255 
   256   if (G_UNLIKELY (g_mem_gc_friendly))
   257     g_array_elt_zero (array, array->len, 1);
   258   else
   259     g_array_zero_terminate (array);
   260 
   261   return farray;
   262 }
   263 
   264 EXPORT_C GArray*
   265 g_array_remove_range (GArray *farray,
   266                       guint   index_,
   267                       guint   length)
   268 {
   269   GRealArray *array = (GRealArray*) farray;
   270 
   271   g_return_val_if_fail (array, NULL);
   272   g_return_val_if_fail (index_ < array->len, NULL);
   273   g_return_val_if_fail (index_ + length <= array->len, NULL);
   274 
   275   if (index_ + length != array->len)
   276     g_memmove (g_array_elt_pos (array, index_), 
   277                g_array_elt_pos (array, index_ + length), 
   278                (array->len - (index_ + length)) * array->elt_size);
   279 
   280   array->len -= length;
   281   if (G_UNLIKELY (g_mem_gc_friendly))
   282     g_array_elt_zero (array, array->len, length);
   283   else
   284     g_array_zero_terminate (array);
   285 
   286   return farray;
   287 }
   288 
   289 EXPORT_C void
   290 g_array_sort (GArray       *farray,
   291 	      GCompareFunc  compare_func)
   292 {
   293   GRealArray *array = (GRealArray*) farray;
   294 
   295   g_return_if_fail (array != NULL);
   296 
   297   qsort (array->data,
   298 	 array->len,
   299 	 array->elt_size,
   300 	 compare_func);
   301 }
   302 
   303 EXPORT_C void
   304 g_array_sort_with_data (GArray           *farray,
   305 			GCompareDataFunc  compare_func,
   306 			gpointer          user_data)
   307 {
   308   GRealArray *array = (GRealArray*) farray;
   309 
   310   g_return_if_fail (array != NULL);
   311 
   312   g_qsort_with_data (array->data,
   313 		     array->len,
   314 		     array->elt_size,
   315 		     compare_func,
   316 		     user_data);
   317 }
   318 
   319 
   320 static gint
   321 g_nearest_pow (gint num)
   322 {
   323   gint n = 1;
   324 
   325   while (n < num)
   326     n <<= 1;
   327 
   328   return n;
   329 }
   330 
   331 static void
   332 g_array_maybe_expand (GRealArray *array,
   333 		      gint        len)
   334 {
   335   guint want_alloc = g_array_elt_len (array, array->len + len + 
   336 				      array->zero_terminated);
   337 
   338   if (want_alloc > array->alloc)
   339     {
   340       want_alloc = g_nearest_pow (want_alloc);
   341       want_alloc = MAX (want_alloc, MIN_ARRAY_SIZE);
   342 
   343       array->data = g_realloc (array->data, want_alloc);
   344 
   345       if (G_UNLIKELY (g_mem_gc_friendly))
   346         memset (array->data + array->alloc, 0, want_alloc - array->alloc);
   347 
   348       array->alloc = want_alloc;
   349     }
   350 }
   351 
   352 /* Pointer Array
   353  */
   354 
   355 typedef struct _GRealPtrArray  GRealPtrArray;
   356 
   357 struct _GRealPtrArray
   358 {
   359   gpointer *pdata;
   360   guint     len;
   361   guint     alloc;
   362 };
   363 
   364 static void g_ptr_array_maybe_expand (GRealPtrArray *array,
   365 				      gint           len);
   366 
   367 EXPORT_C GPtrArray*
   368 g_ptr_array_new (void)
   369 {
   370   return g_ptr_array_sized_new (0);
   371 }
   372 
   373 EXPORT_C GPtrArray*  
   374 g_ptr_array_sized_new (guint reserved_size)
   375 {
   376   GRealPtrArray *array = g_slice_new (GRealPtrArray);
   377 
   378   array->pdata = NULL;
   379   array->len = 0;
   380   array->alloc = 0;
   381 
   382   if (reserved_size != 0)
   383     g_ptr_array_maybe_expand (array, reserved_size);
   384 
   385   return (GPtrArray*) array;  
   386 }
   387 
   388 EXPORT_C gpointer*
   389 g_ptr_array_free (GPtrArray *array,
   390 		  gboolean   free_segment)
   391 {
   392   gpointer* segment;
   393 
   394   g_return_val_if_fail (array, NULL);
   395 
   396   if (free_segment)
   397     {
   398       g_free (array->pdata);
   399       segment = NULL;
   400     }
   401   else
   402     segment = array->pdata;
   403 
   404   g_slice_free1 (sizeof (GRealPtrArray), array);
   405 
   406   return segment;
   407 }
   408 
   409 static void
   410 g_ptr_array_maybe_expand (GRealPtrArray *array,
   411 			  gint           len)
   412 {
   413   if ((array->len + len) > array->alloc)
   414     {
   415       guint old_alloc = array->alloc;
   416       array->alloc = g_nearest_pow (array->len + len);
   417       array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE);
   418       array->pdata = g_realloc (array->pdata, sizeof (gpointer) * array->alloc);
   419       if (G_UNLIKELY (g_mem_gc_friendly))
   420         for ( ; old_alloc < array->alloc; old_alloc++)
   421           array->pdata [old_alloc] = NULL;
   422     }
   423 }
   424 
   425 EXPORT_C void
   426 g_ptr_array_set_size  (GPtrArray *farray,
   427 		       gint	  length)
   428 {
   429   GRealPtrArray* array = (GRealPtrArray*) farray;
   430 
   431   g_return_if_fail (array);
   432 
   433   if (length > array->len)
   434     {
   435       int i;
   436       g_ptr_array_maybe_expand (array, (length - array->len));
   437       /* This is not 
   438        *     memset (array->pdata + array->len, 0,
   439        *            sizeof (gpointer) * (length - array->len));
   440        * to make it really portable. Remember (void*)NULL needn't be
   441        * bitwise zero. It of course is silly not to use memset (..,0,..).
   442        */
   443       for (i = array->len; i < length; i++)
   444 	array->pdata[i] = NULL;
   445     }
   446   if (G_UNLIKELY (g_mem_gc_friendly) && length < array->len)
   447     {
   448       int i;
   449       for (i = length; i < array->len; i++)
   450 	array->pdata[i] = NULL;
   451     }
   452 
   453   array->len = length;
   454 }
   455 
   456 EXPORT_C gpointer
   457 g_ptr_array_remove_index (GPtrArray *farray,
   458 			  guint      index_)
   459 {
   460   GRealPtrArray* array = (GRealPtrArray*) farray;
   461   gpointer result;
   462 
   463   g_return_val_if_fail (array, NULL);
   464 
   465   g_return_val_if_fail (index_ < array->len, NULL);
   466 
   467   result = array->pdata[index_];
   468   
   469   if (index_ != array->len - 1)
   470     g_memmove (array->pdata + index_, array->pdata + index_ + 1, 
   471 	       sizeof (gpointer) * (array->len - index_ - 1));
   472   
   473   array->len -= 1;
   474 
   475   if (G_UNLIKELY (g_mem_gc_friendly))
   476     array->pdata[array->len] = NULL;
   477 
   478   return result;
   479 }
   480 
   481 EXPORT_C gpointer
   482 g_ptr_array_remove_index_fast (GPtrArray *farray,
   483 			       guint      index_)
   484 {
   485   GRealPtrArray* array = (GRealPtrArray*) farray;
   486   gpointer result;
   487 
   488   g_return_val_if_fail (array, NULL);
   489 
   490   g_return_val_if_fail (index_ < array->len, NULL);
   491 
   492   result = array->pdata[index_];
   493   
   494   if (index_ != array->len - 1)
   495     array->pdata[index_] = array->pdata[array->len - 1];
   496 
   497   array->len -= 1;
   498 
   499   if (G_UNLIKELY (g_mem_gc_friendly))
   500     array->pdata[array->len] = NULL;
   501 
   502   return result;
   503 }
   504 
   505 EXPORT_C void
   506 g_ptr_array_remove_range (GPtrArray *farray,
   507                           guint      index_,
   508                           guint      length)
   509 {
   510   GRealPtrArray* array = (GRealPtrArray*) farray;
   511 
   512   g_return_if_fail (array);
   513   g_return_if_fail (index_ < array->len);
   514   g_return_if_fail (index_ + length <= array->len);
   515 
   516   if (index_ + length != array->len)
   517     g_memmove (&array->pdata[index_],
   518                &array->pdata[index_ + length], 
   519                (array->len - (index_ + length)) * sizeof (gpointer));
   520 
   521   array->len -= length;
   522   if (G_UNLIKELY (g_mem_gc_friendly))
   523     {
   524       guint i;
   525       for (i = 0; i < length; i++)
   526         array->pdata[array->len + i] = NULL;
   527     }
   528 }
   529 
   530 EXPORT_C gboolean
   531 g_ptr_array_remove (GPtrArray *farray,
   532 		    gpointer   data)
   533 {
   534   GRealPtrArray* array = (GRealPtrArray*) farray;
   535   guint i;
   536 
   537   g_return_val_if_fail (array, FALSE);
   538 
   539   for (i = 0; i < array->len; i += 1)
   540     {
   541       if (array->pdata[i] == data)
   542 	{
   543 	  g_ptr_array_remove_index (farray, i);
   544 	  return TRUE;
   545 	}
   546     }
   547 
   548   return FALSE;
   549 }
   550 
   551 EXPORT_C gboolean
   552 g_ptr_array_remove_fast (GPtrArray *farray,
   553 			 gpointer   data)
   554 {
   555   GRealPtrArray* array = (GRealPtrArray*) farray;
   556   guint i;
   557 
   558   g_return_val_if_fail (array, FALSE);
   559 
   560   for (i = 0; i < array->len; i += 1)
   561     {
   562       if (array->pdata[i] == data)
   563 	{
   564 	  g_ptr_array_remove_index_fast (farray, i);
   565 	  return TRUE;
   566 	}
   567     }
   568 
   569   return FALSE;
   570 }
   571 
   572 EXPORT_C void
   573 g_ptr_array_add (GPtrArray *farray,
   574 		 gpointer   data)
   575 {
   576   GRealPtrArray* array = (GRealPtrArray*) farray;
   577 
   578   g_return_if_fail (array);
   579 
   580   g_ptr_array_maybe_expand (array, 1);
   581 
   582   array->pdata[array->len++] = data;
   583 }
   584 
   585 EXPORT_C void
   586 g_ptr_array_sort (GPtrArray    *array,
   587 		  GCompareFunc  compare_func)
   588 {
   589   g_return_if_fail (array != NULL);
   590 
   591   qsort (array->pdata,
   592 	 array->len,
   593 	 sizeof (gpointer),
   594 	 compare_func);
   595 }
   596 
   597 EXPORT_C void
   598 g_ptr_array_sort_with_data (GPtrArray        *array,
   599 			    GCompareDataFunc  compare_func,
   600 			    gpointer          user_data)
   601 {
   602   g_return_if_fail (array != NULL);
   603 
   604   g_qsort_with_data (array->pdata,
   605 		     array->len,
   606 		     sizeof (gpointer),
   607 		     compare_func,
   608 		     user_data);
   609 }
   610 
   611 /**
   612  * g_ptr_array_foreach:
   613  * @array: a #GPtrArray
   614  * @func: the function to call for each array element
   615  * @user_data: user data to pass to the function
   616  * 
   617  * Calls a function for each element of a #GPtrArray.
   618  *
   619  * Since: 2.4
   620  **/
   621 EXPORT_C void
   622 g_ptr_array_foreach (GPtrArray *array,
   623                      GFunc      func,
   624                      gpointer   user_data)
   625 {
   626   guint i;
   627 
   628   g_return_if_fail (array);
   629 
   630   for (i = 0; i < array->len; i++)
   631     (*func) (array->pdata[i], user_data);
   632 }
   633 
   634 /* Byte arrays 
   635  */
   636 
   637 EXPORT_C GByteArray* g_byte_array_new (void)
   638 {
   639   return (GByteArray*) g_array_sized_new (FALSE, FALSE, 1, 0);
   640 }
   641 
   642 EXPORT_C GByteArray* g_byte_array_sized_new (guint reserved_size)
   643 {
   644   return (GByteArray*) g_array_sized_new (FALSE, FALSE, 1, reserved_size);
   645 }
   646 
   647 EXPORT_C guint8*	    g_byte_array_free     (GByteArray *array,
   648 			           gboolean    free_segment)
   649 {
   650   return (guint8*) g_array_free ((GArray*) array, free_segment);
   651 }
   652 
   653 EXPORT_C GByteArray* g_byte_array_append   (GByteArray   *array,
   654 				   const guint8 *data,
   655 				   guint         len)
   656 {
   657   g_array_append_vals ((GArray*) array, (guint8*)data, len);
   658 
   659   return array;
   660 }
   661 
   662 EXPORT_C GByteArray* g_byte_array_prepend  (GByteArray   *array,
   663 				   const guint8 *data,
   664 				   guint         len)
   665 {
   666   g_array_prepend_vals ((GArray*) array, (guint8*)data, len);
   667 
   668   return array;
   669 }
   670 
   671 EXPORT_C GByteArray* g_byte_array_set_size (GByteArray *array,
   672 				   guint       length)
   673 {
   674   g_array_set_size ((GArray*) array, length);
   675 
   676   return array;
   677 }
   678 
   679 EXPORT_C GByteArray* g_byte_array_remove_index (GByteArray *array,
   680 				       guint       index_)
   681 {
   682   g_array_remove_index ((GArray*) array, index_);
   683 
   684   return array;
   685 }
   686 
   687 EXPORT_C GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
   688 					    guint       index_)
   689 {
   690   g_array_remove_index_fast ((GArray*) array, index_);
   691 
   692   return array;
   693 }
   694 
   695 EXPORT_C GByteArray*
   696 g_byte_array_remove_range (GByteArray *array,
   697                            guint       index_,
   698                            guint       length)
   699 {
   700   g_return_val_if_fail (array, NULL);
   701   g_return_val_if_fail (index_ < array->len, NULL);
   702   g_return_val_if_fail (index_ + length <= array->len, NULL);
   703 
   704   return (GByteArray *)g_array_remove_range ((GArray*) array, index_, length);
   705 }
   706 
   707 EXPORT_C void
   708 g_byte_array_sort (GByteArray   *array,
   709 		   GCompareFunc  compare_func)
   710 {
   711   g_array_sort ((GArray *) array, compare_func);
   712 }
   713 
   714 EXPORT_C void
   715 g_byte_array_sort_with_data (GByteArray       *array,
   716 			     GCompareDataFunc  compare_func,
   717 			     gpointer          user_data)
   718 {
   719   g_array_sort_with_data ((GArray *) array, compare_func, user_data);
   720 }
   721 
   722 #define __G_ARRAY_C__
   723 #include "galiasdef.c"
   724