4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
7 * This file is part of the device-mapper userspace tools.
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU Lesser General Public License v.2.1.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 struct dm_hash_node
*next
;
27 struct dm_hash_table
{
30 struct dm_hash_node
**slots
;
33 /* Permutation of the Integers 0 through 255 */
34 static unsigned char _nums
[] = {
35 1, 14, 110, 25, 97, 174, 132, 119, 138, 170, 125, 118, 27, 233, 140, 51,
36 87, 197, 177, 107, 234, 169, 56, 68, 30, 7, 173, 73, 188, 40, 36, 65,
37 49, 213, 104, 190, 57, 211, 148, 223, 48, 115, 15, 2, 67, 186, 210, 28,
38 12, 181, 103, 70, 22, 58, 75, 78, 183, 167, 238, 157, 124, 147, 172,
40 176, 161, 141, 86, 60, 66, 128, 83, 156, 241, 79, 46, 168, 198, 41, 254,
41 178, 85, 253, 237, 250, 154, 133, 88, 35, 206, 95, 116, 252, 192, 54,
43 102, 218, 255, 240, 82, 106, 158, 201, 61, 3, 89, 9, 42, 155, 159, 93,
44 166, 80, 50, 34, 175, 195, 100, 99, 26, 150, 16, 145, 4, 33, 8, 189,
45 121, 64, 77, 72, 208, 245, 130, 122, 143, 55, 105, 134, 29, 164, 185,
47 193, 239, 101, 242, 5, 171, 126, 11, 74, 59, 137, 228, 108, 191, 232,
49 6, 24, 81, 20, 127, 17, 91, 92, 251, 151, 225, 207, 21, 98, 113, 112,
50 84, 226, 18, 214, 199, 187, 13, 32, 94, 220, 224, 212, 247, 204, 196,
52 249, 236, 45, 244, 111, 182, 153, 136, 129, 90, 217, 202, 19, 165, 231,
54 230, 142, 96, 227, 62, 179, 246, 114, 162, 53, 160, 215, 205, 180, 47,
56 44, 38, 31, 149, 135, 0, 216, 52, 63, 23, 37, 69, 39, 117, 146, 184,
57 163, 200, 222, 235, 248, 243, 219, 10, 152, 131, 123, 229, 203, 76, 120,
61 static struct dm_hash_node
*_create_node(const char *str
, unsigned len
)
63 struct dm_hash_node
*n
= dm_malloc(sizeof(*n
) + len
);
66 memcpy(n
->key
, str
, len
);
73 static unsigned long _hash(const char *str
, unsigned len
)
75 unsigned long h
= 0, g
;
78 for (i
= 0; i
< len
; i
++) {
80 h
+= _nums
[(unsigned char) *str
++];
81 g
= h
& ((unsigned long) 0xf << 16u);
91 struct dm_hash_table
*dm_hash_create(unsigned size_hint
)
94 unsigned new_size
= 16u;
95 struct dm_hash_table
*hc
= dm_malloc(sizeof(*hc
));
102 memset(hc
, 0, sizeof(*hc
));
104 /* round size hint up to a power of two */
105 while (new_size
< size_hint
)
106 new_size
= new_size
<< 1;
108 hc
->num_slots
= new_size
;
109 len
= sizeof(*(hc
->slots
)) * new_size
;
110 if (!(hc
->slots
= dm_malloc(len
))) {
114 memset(hc
->slots
, 0, len
);
123 static void _free_nodes(struct dm_hash_table
*t
)
125 struct dm_hash_node
*c
, *n
;
128 for (i
= 0; i
< t
->num_slots
; i
++)
129 for (c
= t
->slots
[i
]; c
; c
= n
) {
135 void dm_hash_destroy(struct dm_hash_table
*t
)
142 static struct dm_hash_node
**_find(struct dm_hash_table
*t
, const char *key
,
145 unsigned h
= _hash(key
, len
) & (t
->num_slots
- 1);
146 struct dm_hash_node
**c
;
148 for (c
= &t
->slots
[h
]; *c
; c
= &((*c
)->next
)) {
149 if ((*c
)->keylen
!= len
)
152 if (!memcmp(key
, (*c
)->key
, len
))
159 void *dm_hash_lookup_binary(struct dm_hash_table
*t
, const char *key
,
162 struct dm_hash_node
**c
= _find(t
, key
, len
);
164 return *c
? (*c
)->data
: 0;
167 int dm_hash_insert_binary(struct dm_hash_table
*t
, const char *key
,
168 uint32_t len
, void *data
)
170 struct dm_hash_node
**c
= _find(t
, key
, len
);
175 struct dm_hash_node
*n
= _create_node(key
, len
);
189 void dm_hash_remove_binary(struct dm_hash_table
*t
, const char *key
,
192 struct dm_hash_node
**c
= _find(t
, key
, len
);
195 struct dm_hash_node
*old
= *c
;
202 void *dm_hash_lookup(struct dm_hash_table
*t
, const char *key
)
204 return dm_hash_lookup_binary(t
, key
, strlen(key
) + 1);
207 int dm_hash_insert(struct dm_hash_table
*t
, const char *key
, void *data
)
209 return dm_hash_insert_binary(t
, key
, strlen(key
) + 1, data
);
212 void dm_hash_remove(struct dm_hash_table
*t
, const char *key
)
214 dm_hash_remove_binary(t
, key
, strlen(key
) + 1);
217 unsigned dm_hash_get_num_entries(struct dm_hash_table
*t
)
222 void dm_hash_iter(struct dm_hash_table
*t
, dm_hash_iterate_fn f
)
224 struct dm_hash_node
*c
, *n
;
227 for (i
= 0; i
< t
->num_slots
; i
++)
228 for (c
= t
->slots
[i
]; c
; c
= n
) {
234 void dm_hash_wipe(struct dm_hash_table
*t
)
237 memset(t
->slots
, 0, sizeof(struct dm_hash_node
*) * t
->num_slots
);
241 char *dm_hash_get_key(struct dm_hash_table
*t
__attribute((unused
)),
242 struct dm_hash_node
*n
)
247 void *dm_hash_get_data(struct dm_hash_table
*t
__attribute((unused
)),
248 struct dm_hash_node
*n
)
253 static struct dm_hash_node
*_next_slot(struct dm_hash_table
*t
, unsigned s
)
255 struct dm_hash_node
*c
= NULL
;
258 for (i
= s
; i
< t
->num_slots
&& !c
; i
++)
264 struct dm_hash_node
*dm_hash_get_first(struct dm_hash_table
*t
)
266 return _next_slot(t
, 0);
269 struct dm_hash_node
*dm_hash_get_next(struct dm_hash_table
*t
, struct dm_hash_node
*n
)
271 unsigned h
= _hash(n
->key
, n
->keylen
) & (t
->num_slots
- 1);
273 return n
->next
? n
->next
: _next_slot(t
, h
+ 1);