2 * mono-internal-hash.c: A hash table which uses the values themselves as nodes.
5 * Mark Probst (mark.probst@gmail.com)
7 * (C) 2007 Novell, Inc.
13 #include <mono/utils/mono-compiler.h>
14 #include <mono/utils/mono-internal-hash.h>
17 #define HASH(k,f,s) ((f)((k)) % (s))
20 mono_internal_hash_table_init (MonoInternalHashTable
*table
,
22 MonoInternalHashKeyExtractFunc key_extract
,
23 MonoInternalHashNextValueFunc next_value
)
25 table
->hash_func
= hash_func
;
26 table
->key_extract
= key_extract
;
27 table
->next_value
= next_value
;
29 table
->size
= MIN_SIZE
;
30 table
->num_entries
= 0;
31 table
->table
= g_new0 (gpointer
, table
->size
);
35 mono_internal_hash_table_destroy (MonoInternalHashTable
*table
)
37 g_free (table
->table
);
42 mono_internal_hash_table_lookup (MonoInternalHashTable
*table
, gpointer key
)
46 g_assert (table
->table
!= NULL
);
48 for (value
= table
->table
[HASH (key
, table
->hash_func
, table
->size
)];
50 value
= *(table
->next_value (value
))) {
51 if (table
->key_extract (value
) == key
)
58 resize_if_needed (MonoInternalHashTable
*table
)
64 if (table
->num_entries
< table
->size
* 3)
67 new_size
= g_spaced_primes_closest (table
->num_entries
);
68 new_table
= g_new0 (gpointer
, new_size
);
70 for (i
= 0; i
< table
->size
; ++i
) {
71 while (table
->table
[i
] != NULL
) {
75 value
= table
->table
[i
];
76 table
->table
[i
] = *(table
->next_value (value
));
78 hash
= HASH (table
->key_extract (value
), table
->hash_func
, new_size
);
79 *(table
->next_value (value
)) = new_table
[hash
];
80 new_table
[hash
] = value
;
84 g_free (table
->table
);
86 table
->size
= new_size
;
87 table
->table
= new_table
;
91 mono_internal_hash_table_insert (MonoInternalHashTable
*table
,
92 gpointer key
, gpointer value
)
94 gint hash
= HASH (key
, table
->hash_func
, table
->size
);
96 g_assert (table
->key_extract(value
) == key
);
97 g_assert (*(table
->next_value (value
)) == NULL
);
98 g_assert (mono_internal_hash_table_lookup (table
, key
) == NULL
);
100 *(table
->next_value (value
)) = table
->table
[hash
];
101 table
->table
[hash
] = value
;
103 ++table
->num_entries
;
105 resize_if_needed (table
);
109 mono_internal_hash_table_remove (MonoInternalHashTable
*table
, gpointer key
)
111 gint hash
= HASH (key
, table
->hash_func
, table
->size
);
114 for (value
= &table
->table
[hash
];
116 value
= table
->next_value (*value
)) {
117 if (table
->key_extract (*value
) == key
)
119 *value
= *(table
->next_value (*value
));
120 --table
->num_entries
;