2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2009, 2010 Daniel Borkmann.
4 * Subject to the GPL, version 2.
10 /* Hash table implementation from the GIT project. */
11 /* Copyright 2008 (C) Linus Torvalds, GPL version 2 */
14 * Look up a hash entry in the hash table. Return the pointer to
15 * the existing entry, or the empty slot if none existed. The caller
16 * can then look at the (*ptr) to see whether it existed or not.
18 static struct hash_table_entry
*lookup_hash_entry(unsigned int hash
,
19 const struct hash_table
22 unsigned int size
= table
->size
, nr
= hash
% size
;
23 struct hash_table_entry
*array
= table
->array
;
25 while (array
[nr
].ptr
) {
26 if (array
[nr
].hash
== hash
)
38 * Insert a new hash entry pointer into the table.
40 * If that hash entry already existed, return the pointer to
41 * the existing entry (and the caller can create a list of the
42 * pointers or do anything else). If it didn't exist, return
43 * NULL (and the caller knows the pointer has been inserted).
45 static void **insert_hash_entry(unsigned int hash
, void *ptr
,
46 struct hash_table
*table
)
48 struct hash_table_entry
*entry
= lookup_hash_entry(hash
, table
);
63 * Removes a hash entry pointer from the table.
65 * If that hash does not exist, NULL is returned, or, if that hash
66 * exists and is the first entry, ptr_next will be set to that entry
67 * and NULL is returned. Otherwise the caller must maintain the
70 static void *remove_hash_entry(unsigned int hash
, void *ptr
, void *ptr_next
,
71 struct hash_table
*table
)
73 struct hash_table_entry
*entry
= lookup_hash_entry(hash
, table
);
78 else if (entry
->ptr
== ptr
) {
79 entry
->ptr
= ptr_next
;
90 static void grow_hash_table(struct hash_table
*table
)
93 unsigned int old_size
= table
->size
, new_size
;
94 struct hash_table_entry
*old_array
= table
->array
, *new_array
;
96 new_size
= alloc_nr(old_size
);
97 new_array
= xcalloc(new_size
, sizeof(struct hash_table_entry
));
99 table
->size
= new_size
;
100 table
->array
= new_array
;
103 for (i
= 0; i
< old_size
; i
++) {
104 unsigned int hash
= old_array
[i
].hash
;
105 void *ptr
= old_array
[i
].ptr
;
108 insert_hash_entry(hash
, ptr
, table
);
114 void *lookup_hash(unsigned int hash
, const struct hash_table
*table
)
119 return lookup_hash_entry(hash
, table
)->ptr
;
122 void *remove_hash(unsigned int hash
, void *ptr
, void *ptr_next
,
123 struct hash_table
*table
)
128 return remove_hash_entry(hash
, ptr
, ptr_next
, table
);
131 void **insert_hash(unsigned int hash
, void *ptr
, struct hash_table
*table
)
133 unsigned int nr
= table
->nr
;
135 if (nr
>= table
->size
/2)
136 grow_hash_table(table
);
138 return insert_hash_entry(hash
, ptr
, table
);
141 int for_each_hash(const struct hash_table
*table
, int (*fn
)(void *))
145 unsigned int size
= table
->size
;
146 struct hash_table_entry
*array
= table
->array
;
148 for (i
= 0; i
< size
; i
++) {
149 void *ptr
= array
->ptr
;
164 int for_each_hash_int(const struct hash_table
*table
, int (*fn
)(void *, int),
169 unsigned int size
= table
->size
;
170 struct hash_table_entry
*array
= table
->array
;
172 for (i
= 0; i
< size
; i
++) {
173 void *ptr
= array
->ptr
;
177 int val
= fn(ptr
, arg
);
188 void free_hash(struct hash_table
*table
)