Patch from Morten Welinder to make ghash.c properly obey
[platform/upstream/glib.git] / glib / ghash.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 Lesser 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser 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
20 /*
21  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GLib Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 /* 
28  * MT safe
29  */
30
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 #include "glib.h"
36
37
38 #define HASH_TABLE_MIN_SIZE 11
39 #define HASH_TABLE_MAX_SIZE 13845163
40
41
42 typedef struct _GHashNode      GHashNode;
43
44 struct _GHashNode
45 {
46   gpointer   key;
47   gpointer   value;
48   GHashNode *next;
49 };
50
51 struct _GHashTable
52 {
53   gint             size;
54   gint             nnodes;
55   GHashNode      **nodes;
56   GHashFunc        hash_func;
57   GEqualFunc       key_equal_func;
58   GDestroyNotify   key_destroy_func;
59   GDestroyNotify   value_destroy_func;
60 };
61
62 #define G_HASH_TABLE_RESIZE(hash_table)                         \
63    G_STMT_START {                                               \
64      if ((hash_table->size >= 3 * hash_table->nnodes &&         \
65           hash_table->size > HASH_TABLE_MIN_SIZE) ||            \
66          (3 * hash_table->size <= hash_table->nnodes &&         \
67           hash_table->size < HASH_TABLE_MAX_SIZE))              \
68            g_hash_table_resize (hash_table);                    \
69    } G_STMT_END
70
71 static void             g_hash_table_resize       (GHashTable     *hash_table);
72 static GHashNode**      g_hash_table_lookup_node  (GHashTable     *hash_table,
73                                                    gconstpointer   key);
74 static GHashNode*       g_hash_node_new           (gpointer        key,
75                                                    gpointer        value);
76 static void             g_hash_node_destroy       (GHashNode      *hash_node,
77                                                    GDestroyNotify  key_destroy_func,
78                                                    GDestroyNotify  value_destroy_func);
79 static void             g_hash_nodes_destroy      (GHashNode      *hash_node,
80                                                   GDestroyNotify   key_destroy_func,
81                                                   GDestroyNotify   value_destroy_func);
82 static guint g_hash_table_foreach_remove_or_steal (GHashTable     *hash_table,
83                                                    GHRFunc         func,
84                                                    gpointer        user_data,
85                                                    gboolean        notify);
86
87
88 #ifndef DISABLE_MEM_POOLS
89 G_LOCK_DEFINE_STATIC (g_hash_global);
90
91 static GMemChunk *node_mem_chunk = NULL;
92 static GHashNode *node_free_list = NULL;
93 #endif
94
95 /**
96  * g_hash_table_new:
97  * @hash_func: a function to create a hash value from a key.
98  *   Hash values are used to determine where keys are stored within the
99  *   #GHashTable data structure. The g_direct_hash(), g_int_hash() and 
100  *   g_str_hash() functions are provided for some common types of keys. 
101  *   If hash_func is %NULL, g_direct_hash() is used.
102  * @key_equal_func: a function to check two keys for equality.  This is
103  *   used when looking up keys in the #GHashTable.  The g_direct_equal(),
104  *   g_int_equal() and g_str_equal() functions are provided for the most
105  *   common types of keys. If @key_equal_func is %NULL, keys are compared
106  *   directly in a similar fashion to g_direct_equal(), but without the
107  *   overhead of a function call.
108  *
109  * Creates a new #GHashTable.
110  * 
111  * Return value: a new #GHashTable.
112  **/
113 GHashTable*
114 g_hash_table_new (GHashFunc    hash_func,
115                   GEqualFunc   key_equal_func)
116 {
117   return g_hash_table_new_full (hash_func, key_equal_func, NULL, NULL);
118 }
119
120
121 /**
122  * g_hash_table_new_full:
123  * @hash_func: a function to create a hash value from a key.
124  * @key_equal_func: a function to check two keys for equality.
125  * @key_destroy_func: a function to free the memory allocated for the key 
126  *   used when removing the entry from the #GHashTable or %NULL if you 
127  *   don't want to supply such a function.
128  * @value_destroy_func: a function to free the memory allocated for the 
129  *   value used when removing the entry from the #GHashTable or %NULL if 
130  *   you don't want to supply such a function.
131  * 
132  * Creates a new #GHashTable like g_hash_table_new() and allows to specify
133  * functions to free the memory allocated for the key and value that get 
134  * called when removing the entry from the #GHashTable.
135  * 
136  * Return value: a new #GHashTable.
137  **/
138 GHashTable*
139 g_hash_table_new_full (GHashFunc       hash_func,
140                        GEqualFunc      key_equal_func,
141                        GDestroyNotify  key_destroy_func,
142                        GDestroyNotify  value_destroy_func)
143 {
144   GHashTable *hash_table;
145   guint i;
146   
147   hash_table = g_new (GHashTable, 1);
148   hash_table->size               = HASH_TABLE_MIN_SIZE;
149   hash_table->nnodes             = 0;
150   hash_table->hash_func          = hash_func ? hash_func : g_direct_hash;
151   hash_table->key_equal_func     = key_equal_func;
152   hash_table->key_destroy_func   = key_destroy_func;
153   hash_table->value_destroy_func = value_destroy_func;
154   hash_table->nodes              = g_new (GHashNode*, hash_table->size);
155   
156   for (i = 0; i < hash_table->size; i++)
157     hash_table->nodes[i] = NULL;
158   
159   return hash_table;
160 }
161
162 /**
163  * g_hash_table_destroy:
164  * @hash_table: a #GHashTable.
165  * 
166  * Destroys the #GHashTable. If keys and/or values are dynamically 
167  * allocated, you should either free them first or create the #GHashTable
168  * using g_hash_table_new_full(). In the latter case the destroy functions 
169  * you supplied will be called on all keys and values before destroying 
170  * the #GHashTable.
171  **/
172 void
173 g_hash_table_destroy (GHashTable *hash_table)
174 {
175   guint i;
176   
177   g_return_if_fail (hash_table != NULL);
178   
179   for (i = 0; i < hash_table->size; i++)
180     g_hash_nodes_destroy (hash_table->nodes[i], 
181                           hash_table->key_destroy_func,
182                           hash_table->value_destroy_func);
183   
184   g_free (hash_table->nodes);
185   g_free (hash_table);
186 }
187
188 static inline GHashNode**
189 g_hash_table_lookup_node (GHashTable    *hash_table,
190                           gconstpointer  key)
191 {
192   GHashNode **node;
193   
194   node = &hash_table->nodes
195     [(* hash_table->hash_func) (key) % hash_table->size];
196   
197   /* Hash table lookup needs to be fast.
198    *  We therefore remove the extra conditional of testing
199    *  whether to call the key_equal_func or not from
200    *  the inner loop.
201    */
202   if (hash_table->key_equal_func)
203     while (*node && !(*hash_table->key_equal_func) ((*node)->key, key))
204       node = &(*node)->next;
205   else
206     while (*node && (*node)->key != key)
207       node = &(*node)->next;
208   
209   return node;
210 }
211
212 /**
213  * g_hash_table_lookup:
214  * @hash_table: a #GHashTable.
215  * @key: the key to look up.
216  * 
217  * Looks up a key in a #GHashTable.
218  * 
219  * Return value: the associated value, or %NULL if the key is not found.
220  **/
221 gpointer
222 g_hash_table_lookup (GHashTable   *hash_table,
223                      gconstpointer key)
224 {
225   GHashNode *node;
226   
227   g_return_val_if_fail (hash_table != NULL, NULL);
228   
229   node = *g_hash_table_lookup_node (hash_table, key);
230   
231   return node ? node->value : NULL;
232 }
233
234 /**
235  * g_hash_table_lookup_extended:
236  * @hash_table: a #GHashTable.
237  * @lookup_key: the key to look up.
238  * @orig_key: returns the original key.
239  * @value: returns the value associated with the key.
240  * 
241  * Looks up a key in the #GHashTable, returning the original key and the
242  * associated value and a #gboolean which is %TRUE if the key was found. This 
243  * is useful if you need to free the memory allocated for the original key, 
244  * for example before calling g_hash_table_remove().
245  * 
246  * Return value: %TRUE if the key was found in the #GHashTable.
247  **/
248 gboolean
249 g_hash_table_lookup_extended (GHashTable    *hash_table,
250                               gconstpointer  lookup_key,
251                               gpointer      *orig_key,
252                               gpointer      *value)
253 {
254   GHashNode *node;
255   
256   g_return_val_if_fail (hash_table != NULL, FALSE);
257   
258   node = *g_hash_table_lookup_node (hash_table, lookup_key);
259   
260   if (node)
261     {
262       if (orig_key)
263         *orig_key = node->key;
264       if (value)
265         *value = node->value;
266       return TRUE;
267     }
268   else
269     return FALSE;
270 }
271
272 /**
273  * g_hash_table_insert:
274  * @hash_table: a #GHashTable.
275  * @key: a key to insert.
276  * @value: the value to associate with the key.
277  * 
278  * Inserts a new key and value into a #GHashTable.
279  * 
280  * If the key already exists in the #GHashTable its current value is replaced
281  * with the new value. If you supplied a @value_destroy_func when creating the 
282  * #GHashTable, the old value is freed using that function. If you supplied
283  * a @key_destroy_func when creating the #GHashTable, the passed key is freed 
284  * using that function.
285  **/
286 void
287 g_hash_table_insert (GHashTable *hash_table,
288                      gpointer    key,
289                      gpointer    value)
290 {
291   GHashNode **node;
292   
293   g_return_if_fail (hash_table != NULL);
294   
295   node = g_hash_table_lookup_node (hash_table, key);
296   
297   if (*node)
298     {
299       /* do not reset node->key in this place, keeping
300        * the old key is the intended behaviour. 
301        * g_hash_table_replace() can be used instead.
302        */
303
304       /* free the passed key */
305       if (hash_table->key_destroy_func)
306         hash_table->key_destroy_func (key);
307       
308       if (hash_table->value_destroy_func)
309         hash_table->value_destroy_func ((*node)->value);
310
311       (*node)->value = value;
312     }
313   else
314     {
315       *node = g_hash_node_new (key, value);
316       hash_table->nnodes++;
317       G_HASH_TABLE_RESIZE (hash_table);
318     }
319 }
320
321 /**
322  * g_hash_table_replace:
323  * @hash_table: a #GHashTable.
324  * @key: a key to insert.
325  * @value: the value to associate with the key.
326  * 
327  * Inserts a new key and value into a #GHashTable similar to 
328  * g_hash_table_insert(). The difference is that if the key already exists 
329  * in the #GHashTable, it gets replaced by the new key. If you supplied a 
330  * @value_destroy_func when creating the #GHashTable, the old value is freed 
331  * using that function. If you supplied a @key_destroy_func when creating the 
332  * #GHashTable, the old key is freed using that function. 
333  **/
334 void
335 g_hash_table_replace (GHashTable *hash_table,
336                       gpointer    key,
337                       gpointer    value)
338 {
339   GHashNode **node;
340   
341   g_return_if_fail (hash_table != NULL);
342   
343   node = g_hash_table_lookup_node (hash_table, key);
344   
345   if (*node)
346     {
347       if (hash_table->key_destroy_func)
348         hash_table->key_destroy_func ((*node)->key);
349       
350       if (hash_table->value_destroy_func)
351         hash_table->value_destroy_func ((*node)->value);
352
353       (*node)->key   = key;
354       (*node)->value = value;
355     }
356   else
357     {
358       *node = g_hash_node_new (key, value);
359       hash_table->nnodes++;
360       G_HASH_TABLE_RESIZE (hash_table);
361     }
362 }
363
364 /**
365  * g_hash_table_remove:
366  * @hash_table: a #GHashTable.
367  * @key: the key to remove.
368  * 
369  * Removes a key and its associated value from a #GHashTable.
370  *
371  * If the #GHashTable was created using g_hash_table_new_full(), the
372  * key and value are freed using the supplied destroy functions, otherwise
373  * you have to make sure that any dynamically allocated values are freed 
374  * yourself.
375  * 
376  * Return value: %TRUE if the key was found and removed from the #GHashTable.
377  **/
378 gboolean
379 g_hash_table_remove (GHashTable    *hash_table,
380                      gconstpointer  key)
381 {
382   GHashNode **node, *dest;
383   
384   g_return_val_if_fail (hash_table != NULL, FALSE);
385   
386   node = g_hash_table_lookup_node (hash_table, key);
387   if (*node)
388     {
389       dest = *node;
390       (*node) = dest->next;
391       g_hash_node_destroy (dest, 
392                            hash_table->key_destroy_func,
393                            hash_table->value_destroy_func);
394       hash_table->nnodes--;
395   
396       G_HASH_TABLE_RESIZE (hash_table);
397
398       return TRUE;
399     }
400
401   return FALSE;
402 }
403
404 /**
405  * g_hash_table_steal:
406  * @hash_table: a #GHashTable.
407  * @key: the key to remove.
408  * 
409  * Removes a key and its associated value from a #GHashTable without
410  * calling the key and value destroy functions.
411  *
412  * Return value: %TRUE if the key was found and removed from the #GHashTable.
413  **/
414 gboolean
415 g_hash_table_steal (GHashTable    *hash_table,
416                     gconstpointer  key)
417 {
418   GHashNode **node, *dest;
419   
420   g_return_val_if_fail (hash_table != NULL, FALSE);
421   
422   node = g_hash_table_lookup_node (hash_table, key);
423   if (*node)
424     {
425       dest = *node;
426       (*node) = dest->next;
427       g_hash_node_destroy (dest, NULL, NULL);
428       hash_table->nnodes--;
429   
430       G_HASH_TABLE_RESIZE (hash_table);
431
432       return TRUE;
433     }
434
435   return FALSE;
436 }
437
438 /**
439  * g_hash_table_foreach_remove:
440  * @hash_table: a #GHashTable.
441  * @func: the function to call for each key/value pair.
442  * @user_data: user data to pass to the function.
443  * 
444  * Calls the given function for each key/value pair in the #GHashTable.
445  * If the function returns %TRUE, then the key/value pair is removed from the
446  * #GHashTable. If you supplied key or value destroy functions when creating
447  * the #GHashTable, they are used to free the memory allocated for the removed
448  * keys and values.
449  * 
450  * Return value: the number of key/value pairs removed.
451  **/
452 guint
453 g_hash_table_foreach_remove (GHashTable *hash_table,
454                              GHRFunc     func,
455                              gpointer    user_data)
456 {
457   g_return_val_if_fail (hash_table != NULL, 0);
458   g_return_val_if_fail (func != NULL, 0);
459   
460   return g_hash_table_foreach_remove_or_steal (hash_table, func, user_data, TRUE);
461 }
462
463 /**
464  * g_hash_table_foreach_steal:
465  * @hash_table: a #GHashTable.
466  * @func: the function to call for each key/value pair.
467  * @user_data: user data to pass to the function.
468  * 
469  * Calls the given function for each key/value pair in the #GHashTable.
470  * If the function returns %TRUE, then the key/value pair is removed from the
471  * #GHashTable, but no key or value destroy functions are called.
472  * 
473  * Return value: the number of key/value pairs removed.
474  **/
475 guint
476 g_hash_table_foreach_steal (GHashTable *hash_table,
477                             GHRFunc     func,
478                             gpointer    user_data)
479 {
480   g_return_val_if_fail (hash_table != NULL, 0);
481   g_return_val_if_fail (func != NULL, 0);
482   
483   return g_hash_table_foreach_remove_or_steal (hash_table, func, user_data, FALSE);
484 }
485
486 static guint
487 g_hash_table_foreach_remove_or_steal (GHashTable *hash_table,
488                                       GHRFunc     func,
489                                       gpointer    user_data,
490                                       gboolean    notify)
491 {
492   GHashNode *node, *prev;
493   guint i;
494   guint deleted = 0;
495   
496   for (i = 0; i < hash_table->size; i++)
497     {
498     restart:
499       
500       prev = NULL;
501       
502       for (node = hash_table->nodes[i]; node; prev = node, node = node->next)
503         {
504           if ((* func) (node->key, node->value, user_data))
505             {
506               deleted += 1;
507               
508               hash_table->nnodes -= 1;
509               
510               if (prev)
511                 {
512                   prev->next = node->next;
513                   g_hash_node_destroy (node,
514                                        notify ? hash_table->key_destroy_func : NULL,
515                                        notify ? hash_table->value_destroy_func : NULL);
516                   node = prev;
517                 }
518               else
519                 {
520                   hash_table->nodes[i] = node->next;
521                   g_hash_node_destroy (node,
522                                        notify ? hash_table->key_destroy_func : NULL,
523                                        notify ? hash_table->value_destroy_func : NULL);
524                   goto restart;
525                 }
526             }
527         }
528     }
529   
530   G_HASH_TABLE_RESIZE (hash_table);
531   
532   return deleted;
533 }
534
535 /**
536  * g_hash_table_foreach:
537  * @hash_table: a #GHashTable.
538  * @func: the function to call for each key/value pair.
539  * @user_data: user data to pass to the function.
540  * 
541  * Calls the given function for each of the key/value pairs in the
542  * #GHashTable.  The function is passed the key and value of each
543  * pair, and the given @user_data parameter.  The hash table may not
544  * be modified while iterating over it (you can't add/remove
545  * items). To remove all items matching a predicate, use
546  * g_hash_table_remove().
547  **/
548 void
549 g_hash_table_foreach (GHashTable *hash_table,
550                       GHFunc      func,
551                       gpointer    user_data)
552 {
553   GHashNode *node;
554   gint i;
555   
556   g_return_if_fail (hash_table != NULL);
557   g_return_if_fail (func != NULL);
558   
559   for (i = 0; i < hash_table->size; i++)
560     for (node = hash_table->nodes[i]; node; node = node->next)
561       (* func) (node->key, node->value, user_data);
562 }
563
564 /**
565  * g_hash_table_size:
566  * @hash_table: a #GHashTable.
567  * 
568  * Returns the number of elements contained in the #GHashTable.
569  * 
570  * Return value: the number of key/value pairs in the #GHashTable.
571  **/
572 guint
573 g_hash_table_size (GHashTable *hash_table)
574 {
575   g_return_val_if_fail (hash_table != NULL, 0);
576   
577   return hash_table->nnodes;
578 }
579
580 static void
581 g_hash_table_resize (GHashTable *hash_table)
582 {
583   GHashNode **new_nodes;
584   GHashNode *node;
585   GHashNode *next;
586   guint hash_val;
587   gint new_size;
588   gint i;
589
590   new_size = g_spaced_primes_closest (hash_table->nnodes);
591   new_size = CLAMP (new_size, HASH_TABLE_MIN_SIZE, HASH_TABLE_MAX_SIZE);
592  
593   new_nodes = g_new0 (GHashNode*, new_size);
594   
595   for (i = 0; i < hash_table->size; i++)
596     for (node = hash_table->nodes[i]; node; node = next)
597       {
598         next = node->next;
599
600         hash_val = (* hash_table->hash_func) (node->key) % new_size;
601
602         node->next = new_nodes[hash_val];
603         new_nodes[hash_val] = node;
604       }
605   
606   g_free (hash_table->nodes);
607   hash_table->nodes = new_nodes;
608   hash_table->size = new_size;
609 }
610
611 static GHashNode*
612 g_hash_node_new (gpointer key,
613                  gpointer value)
614 {
615   GHashNode *hash_node;
616   
617 #ifdef DISABLE_MEM_POOLS
618   hash_node = g_new (GHashNode, 1);
619 #else
620   G_LOCK (g_hash_global);
621   if (node_free_list)
622     {
623       hash_node = node_free_list;
624       node_free_list = node_free_list->next;
625     }
626   else
627     {
628       if (!node_mem_chunk)
629         node_mem_chunk = g_mem_chunk_new ("hash node mem chunk",
630                                           sizeof (GHashNode),
631                                           1024, G_ALLOC_ONLY);
632       
633       hash_node = g_chunk_new (GHashNode, node_mem_chunk);
634     }
635   G_UNLOCK (g_hash_global);
636 #endif
637   
638   hash_node->key = key;
639   hash_node->value = value;
640   hash_node->next = NULL;
641   
642   return hash_node;
643 }
644
645 static void
646 g_hash_node_destroy (GHashNode      *hash_node,
647                      GDestroyNotify  key_destroy_func,
648                      GDestroyNotify  value_destroy_func)
649 {
650   if (key_destroy_func)
651     key_destroy_func (hash_node->key);
652   if (value_destroy_func)
653     value_destroy_func (hash_node->value);
654   
655 #ifdef ENABLE_GC_FRIENDLY
656   hash_node->key = NULL;
657   hash_node->value = NULL;
658 #endif /* ENABLE_GC_FRIENDLY */
659
660 #ifdef DISABLE_MEM_POOLS
661   g_free (hash_node);
662 #else
663   G_LOCK (g_hash_global);
664   hash_node->next = node_free_list;
665   node_free_list = hash_node;
666   G_UNLOCK (g_hash_global);
667 #endif
668 }
669
670 static void
671 g_hash_nodes_destroy (GHashNode *hash_node,
672                       GFreeFunc  key_destroy_func,
673                       GFreeFunc  value_destroy_func)
674 {
675 #ifdef DISABLE_MEM_POOLS
676   while (hash_node)
677     {
678       GHashNode *next = hash_node->next;
679
680       if (key_destroy_func)
681         key_destroy_func (hash_node->key);
682       if (value_destroy_func)
683         value_destroy_func (hash_node->value);
684
685       g_free (hash_node);
686       hash_node = next;
687     }  
688 #else
689   if (hash_node)
690     {
691       GHashNode *node = hash_node;
692   
693       while (node->next)
694         {
695           if (key_destroy_func)
696             key_destroy_func (node->key);
697           if (value_destroy_func)
698             value_destroy_func (node->value);
699
700 #ifdef ENABLE_GC_FRIENDLY
701           node->key = NULL;
702           node->value = NULL;
703 #endif /* ENABLE_GC_FRIENDLY */
704
705           node = node->next;
706         }
707
708       if (key_destroy_func)
709         key_destroy_func (node->key);
710       if (value_destroy_func)
711         value_destroy_func (node->value);
712
713 #ifdef ENABLE_GC_FRIENDLY
714       node->key = NULL;
715       node->value = NULL;
716 #endif /* ENABLE_GC_FRIENDLY */
717  
718       G_LOCK (g_hash_global);
719       node->next = node_free_list;
720       node_free_list = hash_node;
721       G_UNLOCK (g_hash_global);
722     }
723 #endif
724 }