3 * A hash table which uses the values themselves as nodes.
6 * Mark Probst (mark.probst@gmail.com)
8 * (C) 2007 Novell, Inc.
14 #include <mono/utils/mono-compiler.h>
15 #include <mono/utils/mono-internal-hash.h>
18 #define HASH(k,f,s) ((f)((k)) % (s))
21 mono_internal_hash_table_init (MonoInternalHashTable
*table
,
23 MonoInternalHashKeyExtractFunc key_extract
,
24 MonoInternalHashNextValueFunc next_value
)
26 table
->hash_func
= hash_func
;
27 table
->key_extract
= key_extract
;
28 table
->next_value
= next_value
;
30 table
->size
= MIN_SIZE
;
31 table
->num_entries
= 0;
32 table
->table
= g_new0 (gpointer
, table
->size
);
36 mono_internal_hash_table_destroy (MonoInternalHashTable
*table
)
38 g_free (table
->table
);
43 mono_internal_hash_table_lookup (MonoInternalHashTable
*table
, gpointer key
)
47 g_assert (table
->table
!= NULL
);
49 for (value
= table
->table
[HASH (key
, table
->hash_func
, table
->size
)];
51 value
= *(table
->next_value (value
))) {
52 if (table
->key_extract (value
) == key
)
59 resize_if_needed (MonoInternalHashTable
*table
)
65 if (table
->num_entries
< table
->size
* 3)
68 new_size
= g_spaced_primes_closest (table
->num_entries
);
69 new_table
= g_new0 (gpointer
, new_size
);
71 for (i
= 0; i
< table
->size
; ++i
) {
72 while (table
->table
[i
] != NULL
) {
76 value
= table
->table
[i
];
77 table
->table
[i
] = *(table
->next_value (value
));
79 hash
= HASH (table
->key_extract (value
), table
->hash_func
, new_size
);
80 *(table
->next_value (value
)) = new_table
[hash
];
81 new_table
[hash
] = value
;
85 g_free (table
->table
);
87 table
->size
= new_size
;
88 table
->table
= new_table
;
92 mono_internal_hash_table_insert (MonoInternalHashTable
*table
,
93 gpointer key
, gpointer value
)
95 gint hash
= HASH (key
, table
->hash_func
, table
->size
);
97 g_assert (table
->key_extract(value
) == key
);
98 g_assert (*(table
->next_value (value
)) == NULL
);
99 g_assert (mono_internal_hash_table_lookup (table
, key
) == NULL
);
101 *(table
->next_value (value
)) = table
->table
[hash
];
102 table
->table
[hash
] = value
;
104 ++table
->num_entries
;
106 resize_if_needed (table
);
110 mono_internal_hash_table_remove (MonoInternalHashTable
*table
, gpointer key
)
112 gint hash
= HASH (key
, table
->hash_func
, table
->size
);
115 for (value
= &table
->table
[hash
];
117 value
= table
->next_value (*value
)) {
118 if (table
->key_extract (*value
) == key
)
120 *value
= *(table
->next_value (*value
));
121 --table
->num_entries
;