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 phead
= &htable
->ht_table
[hash
& (htable
->ht_size
- 1)];
115 TAILQ_FOREACH(pnode
, phead
, hn_next
)
116 if (htable
->ht_cmpf(pnode
->hn_key
, key
) == 0) {
117 pnode
->hn_data
= data
;
121 /* Allocate memory for new entry */
122 if ((pnode
= malloc(sizeof *pnode
)) == NULL
)
125 pnode
->hn_data
= data
;
127 TAILQ_INSERT_TAIL(phead
, pnode
, hn_next
);
129 /* If used items exceeds limit, grow the table */
130 if (++htable
->ht_used
> htable
->ht_limit
)
136 htret_t
htable_remove(htable_t
*htable
, const void *key
)
139 hnode_t
*pnode
, *tmp
;
143 hash
= htable
->ht_hashf(key
);
145 /* Search across chain if there is an entry with the
146 key we are looking. If there is, remove it. */
147 phead
= &htable
->ht_table
[hash
& (htable
->ht_size
- 1)];
148 TAILQ_FOREACH(pnode
, phead
, hn_next
) {
149 if (htable
->ht_cmpf(pnode
->hn_key
, key
) == 0) {
151 TAILQ_REMOVE(phead
, pnode
, hn_next
);
161 void *htable_search(const htable_t
*htable
, const void *key
)
163 const hhead_t
*phead
;
164 const hnode_t
*pnode
;
168 hash
= htable
->ht_hashf(key
);
170 phead
= &htable
->ht_table
[hash
& (htable
->ht_size
- 1)];
171 TAILQ_FOREACH(pnode
, phead
, hn_next
)
172 if (htable
->ht_cmpf(pnode
->hn_key
, key
) == 0)
173 return pnode
->hn_data
;
178 void htable_print(const htable_t
*htable
)
180 const hhead_t
*phead
;
181 const hnode_t
*pnode
;
184 for (i
= 0; i
< htable
->ht_size
; i
++) {
185 phead
= &htable
->ht_table
[i
];
186 TAILQ_FOREACH(pnode
, phead
, hn_next
)
187 htable
->ht_printf(pnode
->hn_key
, pnode
->hn_data
);
188 if (TAILQ_FIRST(&htable
->ht_table
[i
]) != NULL
)