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
)
66 htret_t
htable_grow(htable_t
*htable
)
68 hhead_t
*pcurhead
, *pnewhead
, *poldhead
;
70 unsigned int i
, newhash
, newsize
;
72 /* Allocate memory for new hash table */
73 newsize
= 2 * htable
->ht_size
;
74 if ((pnewhead
= malloc(newsize
* sizeof *pnewhead
)) == NULL
)
77 /* Initialize tailqs */
78 for (i
= 0; i
< newsize
; i
++)
79 TAILQ_INIT(&pnewhead
[i
]);
81 poldhead
= htable
->ht_table
;
83 for (i
= 0; i
< htable
->ht_size
; i
++) {
84 pcurhead
= &poldhead
[i
];
85 while ((pnode
= TAILQ_FIRST(pcurhead
)) != NULL
) {
86 newhash
= htable
->ht_hashf(pnode
->hn_key
);
87 TAILQ_REMOVE(pcurhead
, pnode
, hn_next
);
88 TAILQ_INSERT_TAIL(&pnewhead
[newhash
& (newsize
- 1)], pnode
, hn_next
);
93 free(htable
->ht_table
);
95 /* Set new table parameters */
96 htable
->ht_table
= pnewhead
;
97 htable
->ht_size
= newsize
;
98 htable
->ht_limit
= htable
->ht_factor
* newsize
;
103 htret_t
htable_insert(htable_t
*htable
, const void *key
, void *data
)
110 hash
= htable
->ht_hashf(key
);
112 /* Search across chain if there is already an entry
113 with the same key. If there is, replace it.
114 Don't forget to free the old data, before overwriting
115 the pointer or else we will leak. */
116 phead
= &htable
->ht_table
[hash
& (htable
->ht_size
- 1)];
117 TAILQ_FOREACH(pnode
, phead
, hn_next
)
118 if (htable
->ht_cmpf(pnode
->hn_key
, key
) == 0) {
119 free(pnode
->hn_data
);
120 pnode
->hn_data
= data
;
124 /* Allocate memory for new entry */
125 if ((pnode
= malloc(sizeof *pnode
)) == NULL
)
128 pnode
->hn_data
= data
;
130 TAILQ_INSERT_TAIL(phead
, pnode
, hn_next
);
132 /* If used items exceeds limit, grow the table */
133 if (++htable
->ht_used
> htable
->ht_limit
)
139 htret_t
htable_remove(htable_t
*htable
, const void *key
)
142 hnode_t
*pnode
, *tmp
;
146 hash
= htable
->ht_hashf(key
);
148 /* Search across chain if there is an entry with the
149 key we are looking. If there is, remove it. */
150 phead
= &htable
->ht_table
[hash
& (htable
->ht_size
- 1)];
151 TAILQ_FOREACH(pnode
, phead
, hn_next
) {
152 if (htable
->ht_cmpf(pnode
->hn_key
, key
) == 0) {
154 TAILQ_REMOVE(phead
, pnode
, hn_next
);
164 void *htable_search(const htable_t
*htable
, const void *key
)
166 const hhead_t
*phead
;
167 const hnode_t
*pnode
;
171 hash
= htable
->ht_hashf(key
);
173 phead
= &htable
->ht_table
[hash
& (htable
->ht_size
- 1)];
174 TAILQ_FOREACH(pnode
, phead
, hn_next
)
175 if (htable
->ht_cmpf(pnode
->hn_key
, key
) == 0)
176 return pnode
->hn_data
;
181 void htable_print(const htable_t
*htable
)
183 const hhead_t
*phead
;
184 const hnode_t
*pnode
;
187 for (i
= 0; i
< htable
->ht_size
; i
++) {
188 phead
= &htable
->ht_table
[i
];
189 TAILQ_FOREACH(pnode
, phead
, hn_next
)
190 htable
->ht_printf(pnode
->hn_key
, pnode
->hn_data
);
191 if (TAILQ_FIRST(&htable
->ht_table
[i
]) != NULL
)