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