2 * Copyright (C) 2006-2010 B.A.T.M.A.N. contributors:
4 * Simon Wunderlich, Marek Lindner
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 static void hash_init(struct hashtable_t
*hash
)
32 for (i
= 0 ; i
< hash
->size
; i
++)
33 hash
->table
[i
] = NULL
;
36 /* remove the hash structure. if hashdata_free_cb != NULL, this function will be
37 * called to remove the elements inside of the hash. if you don't remove the
38 * elements, memory might be leaked. */
39 void hash_delete(struct hashtable_t
*hash
, hashdata_free_cb free_cb
, void *arg
)
41 struct element_t
*bucket
, *last_bucket
;
44 for (i
= 0; i
< hash
->size
; i
++) {
45 bucket
= hash
->table
[i
];
47 while (bucket
!= NULL
) {
49 free_cb(bucket
->data
, arg
);
52 bucket
= bucket
->next
;
60 /* free only the hashtable and the hash itself. */
61 void hash_destroy(struct hashtable_t
*hash
)
67 /* iterate though the hash. First element is selected if an iterator
68 * initialized with HASHIT() is supplied as iter. Use the returned
69 * (or supplied) iterator to access the elements until hash_iterate returns
72 struct hash_it_t
*hash_iterate(struct hashtable_t
*hash
,
73 struct hash_it_t
*iter
)
80 /* sanity checks first (if our bucket got deleted in the last
82 if (iter
->bucket
!= NULL
) {
83 if (iter
->first_bucket
!= NULL
) {
84 /* we're on the first element and it got removed after
85 * the last iteration. */
86 if ((*iter
->first_bucket
) != iter
->bucket
) {
87 /* there are still other elements in the list */
88 if ((*iter
->first_bucket
) != NULL
) {
89 iter
->prev_bucket
= NULL
;
90 iter
->bucket
= (*iter
->first_bucket
);
92 &hash
->table
[iter
->index
];
98 } else if (iter
->prev_bucket
!= NULL
) {
100 * we're not on the first element, and the bucket got
101 * removed after the last iteration. the last bucket's
102 * next pointer is not pointing to our actual bucket
103 * anymore. select the next.
105 if (iter
->prev_bucket
->next
!= iter
->bucket
)
106 iter
->bucket
= iter
->prev_bucket
;
110 /* now as we are sane, select the next one if there is some */
111 if (iter
->bucket
!= NULL
) {
112 if (iter
->bucket
->next
!= NULL
) {
113 iter
->prev_bucket
= iter
->bucket
;
114 iter
->bucket
= iter
->bucket
->next
;
115 iter
->first_bucket
= NULL
;
120 /* if not returned yet, we've reached the last one on the index and have
121 * to search forward */
123 /* go through the entries of the hash table */
124 while (iter
->index
< hash
->size
) {
125 if ((hash
->table
[iter
->index
]) != NULL
) {
126 iter
->prev_bucket
= NULL
;
127 iter
->bucket
= hash
->table
[iter
->index
];
128 iter
->first_bucket
= &hash
->table
[iter
->index
];
135 /* nothing to iterate over anymore */
139 /* allocates and clears the hash */
140 struct hashtable_t
*hash_new(int size
, hashdata_compare_cb compare
,
141 hashdata_choose_cb choose
)
143 struct hashtable_t
*hash
;
145 hash
= kmalloc(sizeof(struct hashtable_t
) , GFP_ATOMIC
);
151 hash
->table
= kmalloc(sizeof(struct element_t
*) * size
, GFP_ATOMIC
);
153 if (hash
->table
== NULL
) {
160 hash
->compare
= compare
;
161 hash
->choose
= choose
;
166 /* adds data to the hashtable. returns 0 on success, -1 on error */
167 int hash_add(struct hashtable_t
*hash
, void *data
)
170 struct element_t
*bucket
, *prev_bucket
= NULL
;
175 index
= hash
->choose(data
, hash
->size
);
176 bucket
= hash
->table
[index
];
178 while (bucket
!= NULL
) {
179 if (hash
->compare(bucket
->data
, data
))
182 prev_bucket
= bucket
;
183 bucket
= bucket
->next
;
186 /* found the tail of the list, add new element */
187 bucket
= kmalloc(sizeof(struct element_t
), GFP_ATOMIC
);
196 if (prev_bucket
== NULL
)
197 hash
->table
[index
] = bucket
;
199 prev_bucket
->next
= bucket
;
205 /* finds data, based on the key in keydata. returns the found data on success,
206 * or NULL on error */
207 void *hash_find(struct hashtable_t
*hash
, void *keydata
)
210 struct element_t
*bucket
;
215 index
= hash
->choose(keydata
, hash
->size
);
216 bucket
= hash
->table
[index
];
218 while (bucket
!= NULL
) {
219 if (hash
->compare(bucket
->data
, keydata
))
222 bucket
= bucket
->next
;
228 /* remove bucket (this might be used in hash_iterate() if you already found the
229 * bucket you want to delete and don't need the overhead to find it again with
230 * hash_remove(). But usually, you don't want to use this function, as it
231 * fiddles with hash-internals. */
232 void *hash_remove_bucket(struct hashtable_t
*hash
, struct hash_it_t
*hash_it_t
)
236 data_save
= hash_it_t
->bucket
->data
;
238 if (hash_it_t
->prev_bucket
!= NULL
)
239 hash_it_t
->prev_bucket
->next
= hash_it_t
->bucket
->next
;
240 else if (hash_it_t
->first_bucket
!= NULL
)
241 (*hash_it_t
->first_bucket
) = hash_it_t
->bucket
->next
;
243 kfree(hash_it_t
->bucket
);
249 /* removes data from hash, if found. returns pointer do data on success, so you
250 * can remove the used structure yourself, or NULL on error . data could be the
251 * structure you use with just the key filled, we just need the key for
253 void *hash_remove(struct hashtable_t
*hash
, void *data
)
255 struct hash_it_t hash_it_t
;
257 hash_it_t
.index
= hash
->choose(data
, hash
->size
);
258 hash_it_t
.bucket
= hash
->table
[hash_it_t
.index
];
259 hash_it_t
.prev_bucket
= NULL
;
261 while (hash_it_t
.bucket
!= NULL
) {
262 if (hash
->compare(hash_it_t
.bucket
->data
, data
)) {
263 hash_it_t
.first_bucket
=
265 hash
->table
[hash_it_t
.index
] ?
266 &hash
->table
[hash_it_t
.index
] : NULL
);
267 return hash_remove_bucket(hash
, &hash_it_t
);
270 hash_it_t
.prev_bucket
= hash_it_t
.bucket
;
271 hash_it_t
.bucket
= hash_it_t
.bucket
->next
;
277 /* resize the hash, returns the pointer to the new hash or NULL on
278 * error. removes the old hash on success. */
279 struct hashtable_t
*hash_resize(struct hashtable_t
*hash
, int size
)
281 struct hashtable_t
*new_hash
;
282 struct element_t
*bucket
;
285 /* initialize a new hash with the new size */
286 new_hash
= hash_new(size
, hash
->compare
, hash
->choose
);
288 if (new_hash
== NULL
)
291 /* copy the elements */
292 for (i
= 0; i
< hash
->size
; i
++) {
293 bucket
= hash
->table
[i
];
295 while (bucket
!= NULL
) {
296 hash_add(new_hash
, bucket
->data
);
297 bucket
= bucket
->next
;
301 /* remove hash and eventual overflow buckets but not the content
303 hash_delete(hash
, NULL
, NULL
);