7 htret_t
htable_init(htable_t
*htable
, size_t size
, unsigned int factor
,
8 unsigned int (*hashf
)(const void *key
),
9 int (*cmpf
)(const void *arg1
, const void *arg2
),
10 void (*printf
)(const void *key
, const void *data
))
14 /* Allocate memory for `size' tailq headers */
15 if ((htable
->ht_table
= malloc(size
* sizeof *htable
->ht_table
)) == NULL
)
18 /* Initialize tailqs */
19 for (i
= 0; i
< size
; i
++)
20 TAILQ_INIT(&htable
->ht_table
[i
]);
22 htable
->ht_size
= size
; /* size must be a power of 2 */
24 htable
->ht_factor
= factor
;
25 htable
->ht_limit
= factor
* size
;
27 /* Setup callback functions */
28 htable
->ht_hashf
= hashf
;
29 htable
->ht_cmpf
= cmpf
;
30 htable
->ht_printf
= printf
;
35 void htable_free(htable_t
*htable
)
41 for (i
= 0; i
< htable
->ht_size
; i
++) {
42 phead
= &htable
->ht_table
[i
];
43 while (TAILQ_FIRST(phead
) != NULL
) {
44 pnode
= TAILQ_FIRST(phead
);
45 TAILQ_REMOVE(phead
, TAILQ_FIRST(phead
), hn_next
);
50 free(htable
->ht_table
);
53 void htable_free_objects(htable_t
*htable
)
59 for (i
= 0; i
< htable
->ht_size
; i
++) {
60 phead
= &htable
->ht_table
[i
];
61 TAILQ_FOREACH(pnode
, phead
, hn_next
) {
68 htret_t
htable_grow(htable_t
*htable
)
70 hhead_t
*pcurhead
, *pnewhead
, *poldhead
;
72 unsigned int i
, newhash
, newsize
;
74 /* Allocate memory for new hash table */
75 newsize
= 2 * htable
->ht_size
;
76 if ((pnewhead
= malloc(newsize
* sizeof *pnewhead
)) == NULL
)
79 /* Initialize tailqs */
80 for (i
= 0; i
< newsize
; i
++)
81 TAILQ_INIT(&pnewhead
[i
]);
83 poldhead
= htable
->ht_table
;
85 for (i
= 0; i
< htable
->ht_size
; i
++) {
86 pcurhead
= &poldhead
[i
];
87 while ((pnode
= TAILQ_FIRST(pcurhead
)) != NULL
) {
88 newhash
= htable
->ht_hashf(pnode
->hn_key
);
89 TAILQ_REMOVE(pcurhead
, pnode
, hn_next
);
90 TAILQ_INSERT_TAIL(&pnewhead
[newhash
& (newsize
- 1)], pnode
, hn_next
);
95 free(htable
->ht_table
);
97 /* Set new table parameters */
98 htable
->ht_table
= pnewhead
;
99 htable
->ht_size
= newsize
;
100 htable
->ht_limit
= htable
->ht_factor
* newsize
;
105 htret_t
htable_insert(htable_t
*htable
, const void *key
, void *data
)
112 hash
= htable
->ht_hashf(key
);
114 /* Search across chain if there is already an entry
115 with the same key. If there is, replace it.
116 Don't forget to free the old data, before overwriting
117 the pointer or else we will leak. */
118 phead
= &htable
->ht_table
[hash
& (htable
->ht_size
- 1)];
119 TAILQ_FOREACH(pnode
, phead
, hn_next
)
120 if (htable
->ht_cmpf(pnode
->hn_key
, key
) == 0) {
122 free(pnode
->hn_data
);
124 pnode
->hn_data
= data
;
128 /* Allocate memory for new entry */
129 if ((pnode
= malloc(sizeof *pnode
)) == NULL
)
132 pnode
->hn_data
= data
;
134 TAILQ_INSERT_TAIL(phead
, pnode
, hn_next
);
136 /* If used items exceeds limit, grow the table */
137 if (++htable
->ht_used
> htable
->ht_limit
)
143 htret_t
htable_remove(htable_t
*htable
, const void *key
)
146 hnode_t
*pnode
, *tmp
;
150 hash
= htable
->ht_hashf(key
);
152 /* Search across chain if there is an entry with the
153 key we are looking. If there is, remove it. */
154 phead
= &htable
->ht_table
[hash
& (htable
->ht_size
- 1)];
155 TAILQ_FOREACH(pnode
, phead
, hn_next
) {
156 if (htable
->ht_cmpf(pnode
->hn_key
, key
) == 0) {
158 TAILQ_REMOVE(phead
, pnode
, hn_next
);
168 void *htable_search(const htable_t
*htable
, const void *key
)
170 const hhead_t
*phead
;
171 const hnode_t
*pnode
;
175 hash
= htable
->ht_hashf(key
);
177 phead
= &htable
->ht_table
[hash
& (htable
->ht_size
- 1)];
178 TAILQ_FOREACH(pnode
, phead
, hn_next
)
179 if (htable
->ht_cmpf(pnode
->hn_key
, key
) == 0)
180 return pnode
->hn_data
;
185 void htable_print(const htable_t
*htable
)
187 const hhead_t
*phead
;
188 const hnode_t
*pnode
;
191 for (i
= 0; i
< htable
->ht_size
; i
++) {
192 phead
= &htable
->ht_table
[i
];
193 TAILQ_FOREACH(pnode
, phead
, hn_next
)
194 htable
->ht_printf(pnode
->hn_key
, pnode
->hn_data
);
195 if (TAILQ_FIRST(&htable
->ht_table
[i
]) != NULL
)