(root)/
gettext-0.22.4/
libtextstyle/
lib/
glib/
ghash.c
       1  /* GLIB - Library of useful routines for C programming
       2   * Copyright (C) 2006-2019 Free Software Foundation, Inc.
       3   *
       4   * This file is not part of the GNU gettext program, but is used with
       5   * GNU gettext.
       6   *
       7   * The original copyright notice is as follows:
       8   */
       9  
      10  /* GLIB - Library of useful routines for C programming
      11   * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
      12   *
      13   * This library is free software; you can redistribute it and/or
      14   * modify it under the terms of the GNU Lesser General Public
      15   * License as published by the Free Software Foundation; either
      16   * version 2 of the License, or (at your option) any later version.
      17   *
      18   * This library is distributed in the hope that it will be useful,
      19   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      20   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
      21   * Lesser General Public License for more details.
      22   *
      23   * You should have received a copy of the GNU Lesser General Public
      24   * License along with this library; if not, write to the
      25   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      26   * Boston, MA 02111-1307, USA.
      27   */
      28  
      29  /*
      30   * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
      31   * file for a list of people on the GLib Team.  See the ChangeLog
      32   * files for a list of changes.  These files are distributed with
      33   * GLib at ftp://ftp.gtk.org/pub/gtk/. 
      34   */
      35  
      36  /*
      37   * Modified by Bruno Haible for use as a gnulib module.
      38   */
      39  
      40  /* 
      41   * MT safe
      42   */
      43  
      44  #include "config.h"
      45  
      46  #include "glib.h"
      47  #if 0
      48  #include "galias.h"
      49  #endif
      50  
      51  #undef  CLAMP
      52  #define CLAMP(x, low, high)  (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
      53  
      54  
      55  #define HASH_TABLE_MIN_SIZE 11
      56  #define HASH_TABLE_MAX_SIZE 13845163
      57  
      58  
      59  typedef struct _GHashNode      GHashNode;
      60  
      61  struct _GHashNode
      62  {
      63    gpointer   key;
      64    gpointer   value;
      65    GHashNode *next;
      66  };
      67  
      68  struct _GHashTable
      69  {
      70    gint             size;
      71    gint             nnodes;
      72    GHashNode      **nodes;
      73    GHashFunc        hash_func;
      74    GEqualFunc       key_equal_func;
      75    volatile guint   ref_count;
      76    GDestroyNotify   key_destroy_func;
      77    GDestroyNotify   value_destroy_func;
      78  };
      79  
      80  #define G_HASH_TABLE_RESIZE(hash_table)				\
      81     G_STMT_START {						\
      82       if ((hash_table->size >= 3 * hash_table->nnodes &&	        \
      83  	  hash_table->size > HASH_TABLE_MIN_SIZE) ||		\
      84  	 (3 * hash_table->size <= hash_table->nnodes &&	        \
      85  	  hash_table->size < HASH_TABLE_MAX_SIZE))		\
      86  	   g_hash_table_resize (hash_table);			\
      87     } G_STMT_END
      88  
      89  static void		g_hash_table_resize	  (GHashTable	  *hash_table);
      90  static GHashNode**	g_hash_table_lookup_node  (GHashTable     *hash_table,
      91                                                     gconstpointer   key);
      92  static GHashNode*	g_hash_node_new		  (gpointer	   key,
      93                                                     gpointer        value);
      94  #if 0
      95  static void		g_hash_node_destroy	  (GHashNode	  *hash_node,
      96                                                     GDestroyNotify  key_destroy_func,
      97                                                     GDestroyNotify  value_destroy_func);
      98  static void		g_hash_nodes_destroy	  (GHashNode	  *hash_node,
      99  						  GDestroyNotify   key_destroy_func,
     100  						  GDestroyNotify   value_destroy_func);
     101  static guint g_hash_table_foreach_remove_or_steal (GHashTable     *hash_table,
     102                                                     GHRFunc	   func,
     103                                                     gpointer	   user_data,
     104                                                     gboolean        notify);
     105  #endif
     106  
     107  
     108  /**
     109   * g_hash_table_new:
     110   * @hash_func: a function to create a hash value from a key.
     111   *   Hash values are used to determine where keys are stored within the
     112   *   #GHashTable data structure. The g_direct_hash(), g_int_hash() and 
     113   *   g_str_hash() functions are provided for some common types of keys. 
     114   *   If hash_func is %NULL, g_direct_hash() is used.
     115   * @key_equal_func: a function to check two keys for equality.  This is
     116   *   used when looking up keys in the #GHashTable.  The g_direct_equal(),
     117   *   g_int_equal() and g_str_equal() functions are provided for the most
     118   *   common types of keys. If @key_equal_func is %NULL, keys are compared
     119   *   directly in a similar fashion to g_direct_equal(), but without the
     120   *   overhead of a function call.
     121   *
     122   * Creates a new #GHashTable with a reference count of 1.
     123   * 
     124   * Return value: a new #GHashTable.
     125   **/
     126  GHashTable*
     127  g_hash_table_new (GHashFunc    hash_func,
     128  		  GEqualFunc   key_equal_func)
     129  {
     130    return g_hash_table_new_full (hash_func, key_equal_func, NULL, NULL);
     131  }
     132  
     133  
     134  /**
     135   * g_hash_table_new_full:
     136   * @hash_func: a function to create a hash value from a key.
     137   * @key_equal_func: a function to check two keys for equality.
     138   * @key_destroy_func: a function to free the memory allocated for the key 
     139   *   used when removing the entry from the #GHashTable or %NULL if you 
     140   *   don't want to supply such a function.
     141   * @value_destroy_func: a function to free the memory allocated for the 
     142   *   value used when removing the entry from the #GHashTable or %NULL if 
     143   *   you don't want to supply such a function.
     144   * 
     145   * Creates a new #GHashTable like g_hash_table_new() with a reference count
     146   * of 1 and allows to specify functions to free the memory allocated for the
     147   * key and value that get called when removing the entry from the #GHashTable.
     148   * 
     149   * Return value: a new #GHashTable.
     150   **/
     151  GHashTable*
     152  g_hash_table_new_full (GHashFunc       hash_func,
     153  		       GEqualFunc      key_equal_func,
     154  		       GDestroyNotify  key_destroy_func,
     155  		       GDestroyNotify  value_destroy_func)
     156  {
     157    GHashTable *hash_table;
     158    
     159    hash_table = g_slice_new (GHashTable);
     160    hash_table->size               = HASH_TABLE_MIN_SIZE;
     161    hash_table->nnodes             = 0;
     162    hash_table->hash_func          = hash_func;
     163    hash_table->key_equal_func     = key_equal_func;
     164    hash_table->ref_count          = 1;
     165    hash_table->key_destroy_func   = key_destroy_func;
     166    hash_table->value_destroy_func = value_destroy_func;
     167    hash_table->nodes              = g_new0 (GHashNode*, hash_table->size);
     168    
     169    return hash_table;
     170  }
     171  
     172  #if 0
     173  
     174  /**
     175   * g_hash_table_ref:
     176   * @hash_table: a valid #GHashTable.
     177   * 
     178   * Atomically increments the reference count of @hash_table by one.
     179   * This function is MT-safe and may be called from any thread.
     180   * 
     181   * Return value: the passed in #GHashTable.
     182   * 
     183   * Since: 2.10
     184   **/
     185  GHashTable*
     186  g_hash_table_ref (GHashTable *hash_table)
     187  {
     188    g_return_val_if_fail (hash_table != NULL, NULL);
     189    g_return_val_if_fail (hash_table->ref_count > 0, hash_table);
     190  
     191    g_atomic_int_add (&hash_table->ref_count, 1);
     192    return hash_table;
     193  }
     194  
     195  /**
     196   * g_hash_table_unref:
     197   * @hash_table: a valid #GHashTable.
     198   * 
     199   * Atomically decrements the reference count of @hash_table by one.
     200   * If the reference count drops to 0, all keys and values will be
     201   * destroyed, and all memory allocated by the hash table is released.
     202   * This function is MT-safe and may be called from any thread.
     203   * 
     204   * Since: 2.10
     205   **/
     206  void
     207  g_hash_table_unref (GHashTable *hash_table)
     208  {
     209    g_return_if_fail (hash_table != NULL);
     210    g_return_if_fail (hash_table->ref_count > 0);
     211  
     212    if (g_atomic_int_exchange_and_add (&hash_table->ref_count, -1) - 1 == 0)
     213      {
     214        gint i;
     215  
     216        for (i = 0; i < hash_table->size; i++)
     217          g_hash_nodes_destroy (hash_table->nodes[i], 
     218                                hash_table->key_destroy_func,
     219                                hash_table->value_destroy_func);
     220        g_free (hash_table->nodes);
     221        g_slice_free (GHashTable, hash_table);
     222      }
     223  }
     224  
     225  /**
     226   * g_hash_table_destroy:
     227   * @hash_table: a #GHashTable.
     228   * 
     229   * Destroys all keys and values in the #GHashTable and decrements its
     230   * reference count by 1. If keys and/or values are dynamically allocated,
     231   * you should either free them first or create the #GHashTable with destroy
     232   * notifiers using g_hash_table_new_full(). In the latter case the destroy
     233   * functions you supplied will be called on all keys and values during the
     234   * destruction phase.
     235   **/
     236  void
     237  g_hash_table_destroy (GHashTable *hash_table)
     238  {
     239    g_return_if_fail (hash_table != NULL);
     240    g_return_if_fail (hash_table->ref_count > 0);
     241    
     242    g_hash_table_remove_all (hash_table);
     243    g_hash_table_unref (hash_table);
     244  }
     245  
     246  #endif
     247  
     248  static inline GHashNode**
     249  g_hash_table_lookup_node (GHashTable	*hash_table,
     250  			  gconstpointer	 key)
     251  {
     252    GHashNode **node;
     253    
     254    node = &hash_table->nodes
     255      [(* hash_table->hash_func) (key) % hash_table->size];
     256    
     257    /* Hash table lookup needs to be fast.
     258     *  We therefore remove the extra conditional of testing
     259     *  whether to call the key_equal_func or not from
     260     *  the inner loop.
     261     */
     262    if (hash_table->key_equal_func)
     263      while (*node && !(*hash_table->key_equal_func) ((*node)->key, key))
     264        node = &(*node)->next;
     265    else
     266      while (*node && (*node)->key != key)
     267        node = &(*node)->next;
     268    
     269    return node;
     270  }
     271  
     272  /**
     273   * g_hash_table_lookup:
     274   * @hash_table: a #GHashTable.
     275   * @key: the key to look up.
     276   * 
     277   * Looks up a key in a #GHashTable. Note that this function cannot
     278   * distinguish between a key that is not present and one which is present
     279   * and has the value %NULL. If you need this distinction, use
     280   * g_hash_table_lookup_extended().
     281   * 
     282   * Return value: the associated value, or %NULL if the key is not found.
     283   **/
     284  gpointer
     285  g_hash_table_lookup (GHashTable	  *hash_table,
     286  		     gconstpointer key)
     287  {
     288    GHashNode *node;
     289    
     290    g_return_val_if_fail (hash_table != NULL, NULL);
     291    
     292    node = *g_hash_table_lookup_node (hash_table, key);
     293    
     294    return node ? node->value : NULL;
     295  }
     296  
     297  #if 0
     298  
     299  /**
     300   * g_hash_table_lookup_extended:
     301   * @hash_table: a #GHashTable.
     302   * @lookup_key: the key to look up.
     303   * @orig_key: returns the original key.
     304   * @value: returns the value associated with the key.
     305   * 
     306   * Looks up a key in the #GHashTable, returning the original key and the
     307   * associated value and a #gboolean which is %TRUE if the key was found. This 
     308   * is useful if you need to free the memory allocated for the original key, 
     309   * for example before calling g_hash_table_remove().
     310   * 
     311   * Return value: %TRUE if the key was found in the #GHashTable.
     312   **/
     313  gboolean
     314  g_hash_table_lookup_extended (GHashTable    *hash_table,
     315  			      gconstpointer  lookup_key,
     316  			      gpointer	    *orig_key,
     317  			      gpointer	    *value)
     318  {
     319    GHashNode *node;
     320    
     321    g_return_val_if_fail (hash_table != NULL, FALSE);
     322    
     323    node = *g_hash_table_lookup_node (hash_table, lookup_key);
     324    
     325    if (node)
     326      {
     327        if (orig_key)
     328  	*orig_key = node->key;
     329        if (value)
     330  	*value = node->value;
     331        return TRUE;
     332      }
     333    else
     334      return FALSE;
     335  }
     336  
     337  #endif
     338  
     339  /**
     340   * g_hash_table_insert:
     341   * @hash_table: a #GHashTable.
     342   * @key: a key to insert.
     343   * @value: the value to associate with the key.
     344   * 
     345   * Inserts a new key and value into a #GHashTable.
     346   * 
     347   * If the key already exists in the #GHashTable its current value is replaced
     348   * with the new value. If you supplied a @value_destroy_func when creating the 
     349   * #GHashTable, the old value is freed using that function. If you supplied
     350   * a @key_destroy_func when creating the #GHashTable, the passed key is freed 
     351   * using that function.
     352   **/
     353  void
     354  g_hash_table_insert (GHashTable *hash_table,
     355  		     gpointer	 key,
     356  		     gpointer	 value)
     357  {
     358    GHashNode **node;
     359    
     360    g_return_if_fail (hash_table != NULL);
     361    g_return_if_fail (hash_table->ref_count > 0);
     362    
     363    node = g_hash_table_lookup_node (hash_table, key);
     364    
     365    if (*node)
     366      {
     367        /* do not reset node->key in this place, keeping
     368         * the old key is the intended behaviour. 
     369         * g_hash_table_replace() can be used instead.
     370         */
     371  
     372        /* free the passed key */
     373        if (hash_table->key_destroy_func)
     374  	hash_table->key_destroy_func (key);
     375        
     376        if (hash_table->value_destroy_func)
     377  	hash_table->value_destroy_func ((*node)->value);
     378  
     379        (*node)->value = value;
     380      }
     381    else
     382      {
     383        *node = g_hash_node_new (key, value);
     384        hash_table->nnodes++;
     385        G_HASH_TABLE_RESIZE (hash_table);
     386      }
     387  }
     388  
     389  #if 0
     390  
     391  /**
     392   * g_hash_table_replace:
     393   * @hash_table: a #GHashTable.
     394   * @key: a key to insert.
     395   * @value: the value to associate with the key.
     396   * 
     397   * Inserts a new key and value into a #GHashTable similar to 
     398   * g_hash_table_insert(). The difference is that if the key already exists 
     399   * in the #GHashTable, it gets replaced by the new key. If you supplied a 
     400   * @value_destroy_func when creating the #GHashTable, the old value is freed 
     401   * using that function. If you supplied a @key_destroy_func when creating the 
     402   * #GHashTable, the old key is freed using that function. 
     403   **/
     404  void
     405  g_hash_table_replace (GHashTable *hash_table,
     406  		      gpointer	  key,
     407  		      gpointer	  value)
     408  {
     409    GHashNode **node;
     410    
     411    g_return_if_fail (hash_table != NULL);
     412    g_return_if_fail (hash_table->ref_count > 0);
     413    
     414    node = g_hash_table_lookup_node (hash_table, key);
     415    
     416    if (*node)
     417      {
     418        if (hash_table->key_destroy_func)
     419  	hash_table->key_destroy_func ((*node)->key);
     420        
     421        if (hash_table->value_destroy_func)
     422  	hash_table->value_destroy_func ((*node)->value);
     423  
     424        (*node)->key   = key;
     425        (*node)->value = value;
     426      }
     427    else
     428      {
     429        *node = g_hash_node_new (key, value);
     430        hash_table->nnodes++;
     431        G_HASH_TABLE_RESIZE (hash_table);
     432      }
     433  }
     434  
     435  /**
     436   * g_hash_table_remove:
     437   * @hash_table: a #GHashTable.
     438   * @key: the key to remove.
     439   * 
     440   * Removes a key and its associated value from a #GHashTable.
     441   *
     442   * If the #GHashTable was created using g_hash_table_new_full(), the
     443   * key and value are freed using the supplied destroy functions, otherwise
     444   * you have to make sure that any dynamically allocated values are freed 
     445   * yourself.
     446   * 
     447   * Return value: %TRUE if the key was found and removed from the #GHashTable.
     448   **/
     449  gboolean
     450  g_hash_table_remove (GHashTable	   *hash_table,
     451  		     gconstpointer  key)
     452  {
     453    GHashNode **node, *dest;
     454    
     455    g_return_val_if_fail (hash_table != NULL, FALSE);
     456    
     457    node = g_hash_table_lookup_node (hash_table, key);
     458    if (*node)
     459      {
     460        dest = *node;
     461        (*node) = dest->next;
     462        g_hash_node_destroy (dest, 
     463  			   hash_table->key_destroy_func,
     464  			   hash_table->value_destroy_func);
     465        hash_table->nnodes--;
     466    
     467        G_HASH_TABLE_RESIZE (hash_table);
     468  
     469        return TRUE;
     470      }
     471  
     472    return FALSE;
     473  }
     474  
     475  /**
     476   * g_hash_table_remove_all:
     477   * @hash_table: a #GHashTable
     478   *
     479   * Removes all keys and their associated values from a #GHashTable.
     480   *
     481   * If the #GHashTable was created using g_hash_table_new_full(), the keys
     482   * and values are freed using the supplied destroy functions, otherwise you
     483   * have to make sure that any dynamically allocated values are freed
     484   * yourself.
     485   *
     486   * Since: 2.12
     487   **/
     488  void
     489  g_hash_table_remove_all (GHashTable *hash_table)
     490  {
     491    guint i;
     492  
     493    g_return_if_fail (hash_table != NULL);
     494  
     495    for (i = 0; i < hash_table->size; i++)
     496      {
     497        g_hash_nodes_destroy (hash_table->nodes[i],
     498                              hash_table->key_destroy_func,
     499                              hash_table->value_destroy_func);
     500        hash_table->nodes[i] = NULL;
     501      }
     502    hash_table->nnodes = 0;
     503    
     504    G_HASH_TABLE_RESIZE (hash_table);
     505  }
     506  
     507  /**
     508   * g_hash_table_steal:
     509   * @hash_table: a #GHashTable.
     510   * @key: the key to remove.
     511   * 
     512   * Removes a key and its associated value from a #GHashTable without
     513   * calling the key and value destroy functions.
     514   *
     515   * Return value: %TRUE if the key was found and removed from the #GHashTable.
     516   **/
     517  gboolean
     518  g_hash_table_steal (GHashTable    *hash_table,
     519                      gconstpointer  key)
     520  {
     521    GHashNode **node, *dest;
     522    
     523    g_return_val_if_fail (hash_table != NULL, FALSE);
     524    
     525    node = g_hash_table_lookup_node (hash_table, key);
     526    if (*node)
     527      {
     528        dest = *node;
     529        (*node) = dest->next;
     530        g_hash_node_destroy (dest, NULL, NULL);
     531        hash_table->nnodes--;
     532    
     533        G_HASH_TABLE_RESIZE (hash_table);
     534  
     535        return TRUE;
     536      }
     537  
     538    return FALSE;
     539  }
     540  
     541  /**
     542   * g_hash_table_steal_all:
     543   * @hash_table: a #GHashTable.
     544   *
     545   * Removes all keys and their associated values from a #GHashTable 
     546   * without calling the key and value destroy functions.
     547   *
     548   * Since: 2.12
     549   **/
     550  void
     551  g_hash_table_steal_all (GHashTable *hash_table)
     552  {
     553    guint i;
     554  
     555    g_return_if_fail (hash_table != NULL);
     556  
     557    for (i = 0; i < hash_table->size; i++)
     558      {
     559        g_hash_nodes_destroy (hash_table->nodes[i], NULL, NULL);
     560        hash_table->nodes[i] = NULL;
     561      }
     562  
     563    hash_table->nnodes = 0;
     564  
     565    G_HASH_TABLE_RESIZE (hash_table);
     566  }
     567  
     568  /**
     569   * g_hash_table_foreach_remove:
     570   * @hash_table: a #GHashTable.
     571   * @func: the function to call for each key/value pair.
     572   * @user_data: user data to pass to the function.
     573   * 
     574   * Calls the given function for each key/value pair in the #GHashTable.
     575   * If the function returns %TRUE, then the key/value pair is removed from the
     576   * #GHashTable. If you supplied key or value destroy functions when creating
     577   * the #GHashTable, they are used to free the memory allocated for the removed
     578   * keys and values.
     579   * 
     580   * Return value: the number of key/value pairs removed.
     581   **/
     582  guint
     583  g_hash_table_foreach_remove (GHashTable	*hash_table,
     584  			     GHRFunc	 func,
     585  			     gpointer	 user_data)
     586  {
     587    g_return_val_if_fail (hash_table != NULL, 0);
     588    g_return_val_if_fail (func != NULL, 0);
     589    
     590    return g_hash_table_foreach_remove_or_steal (hash_table, func, user_data, TRUE);
     591  }
     592  
     593  /**
     594   * g_hash_table_foreach_steal:
     595   * @hash_table: a #GHashTable.
     596   * @func: the function to call for each key/value pair.
     597   * @user_data: user data to pass to the function.
     598   * 
     599   * Calls the given function for each key/value pair in the #GHashTable.
     600   * If the function returns %TRUE, then the key/value pair is removed from the
     601   * #GHashTable, but no key or value destroy functions are called.
     602   * 
     603   * Return value: the number of key/value pairs removed.
     604   **/
     605  guint
     606  g_hash_table_foreach_steal (GHashTable *hash_table,
     607                              GHRFunc	func,
     608                              gpointer	user_data)
     609  {
     610    g_return_val_if_fail (hash_table != NULL, 0);
     611    g_return_val_if_fail (func != NULL, 0);
     612    
     613    return g_hash_table_foreach_remove_or_steal (hash_table, func, user_data, FALSE);
     614  }
     615  
     616  static guint
     617  g_hash_table_foreach_remove_or_steal (GHashTable *hash_table,
     618                                        GHRFunc	  func,
     619                                        gpointer	  user_data,
     620                                        gboolean    notify)
     621  {
     622    GHashNode *node, *prev;
     623    gint i;
     624    guint deleted = 0;
     625    
     626    for (i = 0; i < hash_table->size; i++)
     627      {
     628      restart:
     629        
     630        prev = NULL;
     631        
     632        for (node = hash_table->nodes[i]; node; prev = node, node = node->next)
     633  	{
     634  	  if ((* func) (node->key, node->value, user_data))
     635  	    {
     636  	      deleted += 1;
     637  	      
     638  	      hash_table->nnodes -= 1;
     639  	      
     640  	      if (prev)
     641  		{
     642  		  prev->next = node->next;
     643  		  g_hash_node_destroy (node,
     644  				       notify ? hash_table->key_destroy_func : NULL,
     645  				       notify ? hash_table->value_destroy_func : NULL);
     646  		  node = prev;
     647  		}
     648  	      else
     649  		{
     650  		  hash_table->nodes[i] = node->next;
     651  		  g_hash_node_destroy (node,
     652  				       notify ? hash_table->key_destroy_func : NULL,
     653  				       notify ? hash_table->value_destroy_func : NULL);
     654  		  goto restart;
     655  		}
     656  	    }
     657  	}
     658      }
     659    
     660    G_HASH_TABLE_RESIZE (hash_table);
     661    
     662    return deleted;
     663  }
     664  
     665  /**
     666   * g_hash_table_foreach:
     667   * @hash_table: a #GHashTable.
     668   * @func: the function to call for each key/value pair.
     669   * @user_data: user data to pass to the function.
     670   * 
     671   * Calls the given function for each of the key/value pairs in the
     672   * #GHashTable.  The function is passed the key and value of each
     673   * pair, and the given @user_data parameter.  The hash table may not
     674   * be modified while iterating over it (you can't add/remove
     675   * items). To remove all items matching a predicate, use
     676   * g_hash_table_foreach_remove().
     677   **/
     678  void
     679  g_hash_table_foreach (GHashTable *hash_table,
     680  		      GHFunc	  func,
     681  		      gpointer	  user_data)
     682  {
     683    GHashNode *node;
     684    gint i;
     685    
     686    g_return_if_fail (hash_table != NULL);
     687    g_return_if_fail (func != NULL);
     688    
     689    for (i = 0; i < hash_table->size; i++)
     690      for (node = hash_table->nodes[i]; node; node = node->next)
     691        (* func) (node->key, node->value, user_data);
     692  }
     693  
     694  /**
     695   * g_hash_table_find:
     696   * @hash_table: a #GHashTable.
     697   * @predicate:  function to test the key/value pairs for a certain property.
     698   * @user_data:  user data to pass to the function.
     699   * 
     700   * Calls the given function for key/value pairs in the #GHashTable until 
     701   * @predicate returns %TRUE.  The function is passed the key and value of 
     702   * each pair, and the given @user_data parameter. The hash table may not
     703   * be modified while iterating over it (you can't add/remove items). 
     704   *
     705   * Return value: The value of the first key/value pair is returned, for which 
     706   * func evaluates to %TRUE. If no pair with the requested property is found, 
     707   * %NULL is returned.
     708   *
     709   * Since: 2.4
     710   **/
     711  gpointer
     712  g_hash_table_find (GHashTable	   *hash_table,
     713                     GHRFunc	    predicate,
     714                     gpointer	    user_data)
     715  {
     716    GHashNode *node;
     717    gint i;
     718    
     719    g_return_val_if_fail (hash_table != NULL, NULL);
     720    g_return_val_if_fail (predicate != NULL, NULL);
     721    
     722    for (i = 0; i < hash_table->size; i++)
     723      for (node = hash_table->nodes[i]; node; node = node->next)
     724        if (predicate (node->key, node->value, user_data))
     725          return node->value;       
     726    return NULL;
     727  }
     728  
     729  /**
     730   * g_hash_table_size:
     731   * @hash_table: a #GHashTable.
     732   * 
     733   * Returns the number of elements contained in the #GHashTable.
     734   * 
     735   * Return value: the number of key/value pairs in the #GHashTable.
     736   **/
     737  guint
     738  g_hash_table_size (GHashTable *hash_table)
     739  {
     740    g_return_val_if_fail (hash_table != NULL, 0);
     741    
     742    return hash_table->nnodes;
     743  }
     744  
     745  #endif
     746  
     747  static void
     748  g_hash_table_resize (GHashTable *hash_table)
     749  {
     750    GHashNode **new_nodes;
     751    GHashNode *node;
     752    GHashNode *next;
     753    guint hash_val;
     754    gint new_size;
     755    gint i;
     756  
     757    new_size = g_spaced_primes_closest (hash_table->nnodes);
     758    new_size = CLAMP (new_size, HASH_TABLE_MIN_SIZE, HASH_TABLE_MAX_SIZE);
     759   
     760    new_nodes = g_new0 (GHashNode*, new_size);
     761    
     762    for (i = 0; i < hash_table->size; i++)
     763      for (node = hash_table->nodes[i]; node; node = next)
     764        {
     765  	next = node->next;
     766  
     767  	hash_val = (* hash_table->hash_func) (node->key) % new_size;
     768  
     769  	node->next = new_nodes[hash_val];
     770  	new_nodes[hash_val] = node;
     771        }
     772    
     773    g_free (hash_table->nodes);
     774    hash_table->nodes = new_nodes;
     775    hash_table->size = new_size;
     776  }
     777  
     778  static GHashNode*
     779  g_hash_node_new (gpointer key,
     780  		 gpointer value)
     781  {
     782    GHashNode *hash_node = g_slice_new (GHashNode);
     783    
     784    hash_node->key = key;
     785    hash_node->value = value;
     786    hash_node->next = NULL;
     787    
     788    return hash_node;
     789  }
     790  
     791  #if 0
     792  
     793  static void
     794  g_hash_node_destroy (GHashNode      *hash_node,
     795  		     GDestroyNotify  key_destroy_func,
     796  		     GDestroyNotify  value_destroy_func)
     797  {
     798    if (key_destroy_func)
     799      key_destroy_func (hash_node->key);
     800    if (value_destroy_func)
     801      value_destroy_func (hash_node->value);
     802    g_slice_free (GHashNode, hash_node);
     803  }
     804  
     805  static void
     806  g_hash_nodes_destroy (GHashNode *hash_node,
     807  		      GFreeFunc  key_destroy_func,
     808  		      GFreeFunc  value_destroy_func)
     809  {
     810    while (hash_node)
     811      {
     812        GHashNode *next = hash_node->next;
     813        if (key_destroy_func)
     814  	key_destroy_func (hash_node->key);
     815        if (value_destroy_func)
     816  	value_destroy_func (hash_node->value);
     817        g_slice_free (GHashNode, hash_node);
     818        hash_node = next;
     819      }
     820  }
     821  
     822  
     823  #define __G_HASH_C__
     824  #include "galiasdef.c"
     825  #endif