5
* The HashSet contains an array +elems+ of the elements that have been added.
6
* It always has +size+ elements so +size+ ane +elems+ can be used to iterate
7
* over all alements in the HashSet. It also uses a HashTable to keep track of
8
* which elements have been added and their index in the +elems+ array.
10
static HashSet *hs_alloc(void (*free_elem) (void *p))
12
HashSet *hs = ALLOC(HashSet);
14
hs->capa = HS_MIN_SIZE;
15
hs->elems = ALLOC_N(void *, HS_MIN_SIZE);
16
hs->free_elem_i = free_elem ? free_elem : &dummy_free;
20
HashSet *hs_new(unsigned long (*hash)(const void *p),
21
int (*eq)(const void *p1, const void *p2),
22
void (*free_elem)(void *p))
24
HashSet *hs = hs_alloc(free_elem);
25
hs->ht = h_new(hash, eq, NULL, &free);
29
HashSet *hs_new_str(void (*free_elem) (void *p))
31
HashSet *hs = hs_alloc(free_elem);
32
hs->ht = h_new_str((free_ft) NULL, &free);
36
void hs_free(HashSet *hs)
43
void hs_clear(HashSet *hs)
46
for (i = hs->size - 1; i >= 0; i--) {
47
hs_del(hs, hs->elems[i]);
51
void hs_destroy(HashSet *hs)
54
if (hs->free_elem_i != &dummy_free) {
55
for (i = 0; i < hs->size; i++) {
56
hs->free_elem_i(hs->elems[i]);
64
int hs_add(HashSet *hs, void *elem)
66
int has_elem = h_has_key(hs->ht, elem);
67
if (has_elem == HASH_KEY_EQUAL) {
68
/* We don't want to keep two of the same elem so free if necessary */
69
hs->free_elem_i(elem);
71
else if (has_elem == HASH_KEY_SAME) {
72
/* No need to do anything */
75
/* add the elem to the array, resizing if necessary */
76
if (hs->size >= hs->capa) {
78
REALLOC_N(hs->elems, void *, hs->capa);
80
hs->elems[hs->size] = elem;
81
h_set(hs->ht, elem, imalloc(hs->size));
87
int hs_add_safe(HashSet *hs, void *elem)
89
int has_elem = h_has_key(hs->ht, elem);
90
if (has_elem == HASH_KEY_EQUAL) {
91
/* element can't be added */
94
else if (has_elem == HASH_KEY_SAME) {
95
/* the exact same element has already been added */
99
/* add the elem to the array, resizing if necessary */
100
if (hs->size >= hs->capa) {
102
REALLOC_N(hs->elems, void *, hs->capa);
104
hs->elems[hs->size] = elem;
105
h_set(hs->ht, elem, imalloc(hs->size));
111
int hs_del(HashSet *hs, void *elem)
113
void *tmp_elem = hs_rem(hs, elem);
114
if (tmp_elem != NULL) {
115
hs->free_elem_i(tmp_elem);
123
void *hs_rem(HashSet *hs, void *elem)
126
int *index = (int *)h_get(hs->ht, elem);
133
ret_elem = hs->elems[i];
136
for (j = i; j < hs->size; j++) {
137
hs->elems[j] = hs->elems[j+1];
138
h_set(hs->ht, hs->elems[j], imalloc(j));
144
int hs_exists(HashSet *hs, void *elem)
146
return h_has_key(hs->ht, elem);
149
HashSet *hs_merge(HashSet *hs, HashSet * other)
152
for (i = 0; i < other->size; i++) {
153
hs_add(hs, other->elems[i]);
155
/* Now free the other hashset. It is no longer needed. No need, however, to
156
* delete the elements as they're either destroyed or in the new hash set */
161
void *hs_orig(HashSet *hs, void *elem)
163
int *index = h_get(hs->ht, elem);
165
return hs->elems[*index];