"Fossies" - the Fresh Open Source Software Archive 
Member "FunctionCheck-3.2.0/src/fcmanager/fc_xlhash.c" (26 May 2012, 11231 Bytes) of package /linux/privat/old/FunctionCheck-3.2.0.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 #include "fc_tools.h"
2 #include "fc_xlhash.h"
3
4 /* list of prime numbers to compute size of the hash-table */
5 static const unsigned int fc_primes[] ={
6 109,
7 163,
8 251,
9 367,
10 557,
11 823,
12 1237,
13 1861,
14 2777,
15 4177,
16 6247,
17 9371,
18 14057,
19 21089,
20 31627,
21 47431,
22 71143,
23 106721,
24 160073,
25 240101,
26 360163,
27 540217,
28 810343,
29 1215497,
30 1823231,
31 2734867,
32 4102283,
33 6153409,
34 9230113,
35 13845163,
36 };
37
38 static const unsigned fc_nprimes = sizeof (fc_primes) / sizeof (fc_primes[0]);
39
40 /* gives the nearest prime number */
41 static unsigned int fc_spaced_primes_closest(unsigned int num)
42 {
43 unsigned int i;
44
45 for (i = 0; i < fc_nprimes; i++)
46 if (fc_primes[i] > num)
47 return (fc_primes[i]);
48
49 return (fc_primes[fc_nprimes - 1]);
50 }
51
52 /* gives the first prime number */
53 #define fc_first_prime_number() (fc_primes[0])
54
55 /* (!) create a hash-table */
56 FC_LHash *fc_lhash_new(void)
57 {
58 FC_LHash *hash;
59 int i;
60
61 hash = malloc(sizeof (FC_LHash));
62 if (hash == NULL)
63 {
64 fc_message("cannot allocate a lhash-table");
65 return NULL;
66 }
67 /* create the initial list of nodes */
68 hash->nodes = calloc(fc_first_prime_number(), sizeof (FC_LHNode*));
69 if (hash->nodes == NULL)
70 {
71 fc_message("cannot allocate nodes list for a lhash-table");
72 free(hash);
73 return NULL;
74 }
75
76 /* create the initial nodes */
77 hash->nb_rnodes = 0;
78 hash->max_rnodes = 64;
79 hash->rnodes = calloc(hash->max_rnodes, sizeof (FC_LHNode));
80 if (hash->rnodes == NULL)
81 {
82 fc_message("cannot allocate nodes for a lhash-table");
83 free(hash->rnodes);
84 free(hash);
85 return NULL;
86 }
87
88 /* initialize the nodes */
89 for (i = 0; i < hash->max_rnodes; i++)
90 {
91 hash->rnodes[i].fnext = i < hash->max_rnodes - 1 ? &(hash->rnodes[i + 1]) : NULL;
92 }
93 hash->free_entry = &(hash->rnodes[0]);
94
95 /* initialize the elements */
96 hash->size = fc_first_prime_number();
97 hash->nb = 0;
98 hash->frozen = 0;
99 hash->nb_add_rnodes = 0;
100 for (i = 0; i < FC_LHASH_MAX_ADD; i++)
101 {
102 hash->add_rnodes[i] = NULL;
103 }
104
105 return hash;
106 }
107
108 /* (!) destroy a hash-table */
109 void fc_lhash_destroy(FC_LHash *hash)
110 {
111 int i;
112
113 if (hash == NULL)
114 return;
115
116 if (hash->nodes != NULL)
117 free(hash->nodes);
118 if (hash->rnodes != NULL)
119 free(hash->rnodes);
120 for (i = 0; i < hash->nb_add_rnodes; i++)
121 {
122 if (hash->add_rnodes[i] != NULL)
123 free(hash->add_rnodes[i]);
124 }
125 free(hash);
126 }
127
128 /* (!) found a free entry in the rnode list */
129 static FC_LHNode *fc_lhash_get_a_node(FC_LHash *hash)
130 {
131 FC_LHNode *tmp;
132 int i;
133
134 /* get the next available node */
135 tmp = hash->free_entry;
136 /* this entry is no more free */
137 hash->free_entry = tmp->fnext;
138
139 hash->nb_rnodes++;
140
141 /* no more entry available (after this one) */
142 if (hash->free_entry == NULL)
143 {
144 /* reallocation of the list */
145
146 /* no more blocks of nodes available */
147 if (hash->nb_add_rnodes == FC_LHASH_MAX_ADD)
148 {
149 /* nax number of node blocks */
150 fc_message("no more block of nodes availalbe. LTable destroyed.");
151 fc_lhash_destroy(hash);
152 return NULL;
153 }
154
155 /* allocate a new block of nodes */
156 hash->add_rnodes[hash->nb_add_rnodes] =
157 malloc(sizeof (FC_LHNode)*(2 * hash->max_rnodes));
158 if (hash->add_rnodes[hash->nb_add_rnodes] == NULL)
159 {
160 fc_message("cannot reallocate nodes for a lhash-table. Table destroyed.");
161 fc_lhash_destroy(hash);
162 return NULL;
163 }
164
165 /* initialize the new list of nodes */
166 for (i = 0; i < 2 * hash->max_rnodes; i++)
167 {
168 hash->add_rnodes[hash->nb_add_rnodes][i].fnext =
169 (i < 2 * hash->max_rnodes - 1) ? &(hash->add_rnodes[hash->nb_add_rnodes][i + 1]) : NULL;
170 }
171 hash->free_entry = &(hash->add_rnodes[hash->nb_add_rnodes][0]);
172 hash->max_rnodes *= 2;
173 hash->nb_add_rnodes++;
174 }
175
176 return tmp;
177 }
178
179 /* insert the given node in the temporary list */
180
181 /* the field fnext is used to keep the new links */
182 static void fc_lhash_insert_known(FC_LHNode **nodes, FC_LHNode *nd, int size)
183 {
184 int index;
185 FC_LHNode *tmp;
186
187 /* compute its new index */
188 index = (unsigned int) (nd->key % size);
189
190 nd->next = NULL;
191 if (nodes[index] == NULL)
192 {
193 nodes[index] = nd;
194 }
195 else
196 {
197 tmp = nodes[index];
198 while (tmp->next != NULL)
199 {
200 tmp = tmp->next;
201 }
202 tmp->next = nd;
203 }
204 }
205
206 /* (!) increase the size of the hash-table */
207 static void fc_lhash_increase_size(FC_LHash *hash)
208 {
209 FC_LHNode **new_nodes = NULL, *tmp = NULL;
210 int new_size = 0;
211 int i;
212
213 if (hash->frozen)
214 return;
215
216 /* to prevent re-calls to this functions */
217 hash->frozen = 1;
218
219 new_size = (int) fc_spaced_primes_closest((unsigned int) hash->size);
220
221 /* create the new list */
222 new_nodes = calloc(new_size, sizeof (FC_LHNode*));
223
224 /* for each existing entry, re-hash it in the new table */
225 for (i = 0; i < hash->size; i++)
226 {
227 tmp = hash->nodes[i];
228 while (tmp != NULL)
229 {
230 /* remove it from the current list */
231 hash->nodes[i] = tmp->next;
232 /* and re-insert it in the table (without creation) */
233 fc_lhash_insert_known(new_nodes, tmp, new_size);
234
235 /* agin until this part is empty */
236 tmp = hash->nodes[i];
237 }
238 }
239
240 /* replace the new list */
241 hash->nodes = new_nodes;
242 hash->size = new_size;
243
244 hash->frozen = 0;
245 }
246
247 /* debug */
248 void fc_lhash_debug(FC_LHash *hash)
249 {
250 int i;
251 FC_LHNode *tmp;
252
253 if (hash == NULL)
254 return;
255
256 for (i = 0; i < hash->size; i++)
257 {
258 printf("Point %d: [%p]\n", i, hash->nodes[i]);
259 tmp = hash->nodes[i];
260 while (tmp != NULL)
261 {
262 printf("k=%llu [%p] : ", tmp->key, tmp);
263 tmp = tmp->next;
264 }
265 printf("\n");
266 }
267 }
268
269 /* returns the corresp. node if any */
270 static FC_LHNode *fc_lhash_lookup_node(FC_LHash *hash, unsigned long long key)
271 {
272 int index;
273 FC_LHNode *tmp;
274
275 if ((hash == NULL) || (key == 0))
276 return NULL;
277
278 /* compute the hash position */
279 index = (unsigned int) (key % hash->size);
280
281 tmp = hash->nodes[index];
282
283 while (tmp != NULL)
284 {
285 if (tmp->key == key)
286 {
287 return (tmp);
288 }
289 tmp = tmp->next;
290 }
291
292 /* not found */
293 return NULL;
294 }
295
296 /* (!) insert an element in a hash-table */
297 void fc_lhash_insert(FC_LHash *hash, unsigned long long key,
298 int val, void *ptr1, void *ptr2)
299 {
300 int index;
301 FC_LHNode *tmp, *pos;
302
303 if ((hash == NULL) || (key == 0))
304 return;
305
306 /* first try to get the element */
307 tmp = fc_lhash_lookup_node(hash, key);
308
309 /* still here, just modify it */
310 if (tmp != NULL)
311 {
312 tmp->key = key;
313 tmp->value = val;
314 tmp->ptr1 = ptr1;
315 tmp->ptr2 = ptr2;
316 return;
317 }
318
319 /* compute the hash position */
320 index = (unsigned int) (key % hash->size);
321
322 /* get a new node */
323 tmp = fc_lhash_get_a_node(hash);
324 tmp->key = key;
325 tmp->value = val;
326 tmp->ptr1 = ptr1;
327 tmp->ptr2 = ptr2;
328
329 /* insert it */
330 tmp->next = NULL;
331 if (hash->nodes[index] == NULL)
332 {
333 hash->nodes[index] = tmp;
334 }
335 else
336 {
337 pos = hash->nodes[index];
338 while (pos->next != NULL)
339 {
340 pos = pos->next;
341 }
342 pos->next = tmp;
343 }
344
345 /* one more element */
346 hash->nb++;
347
348 /* if the number of element is too high, resize */
349 if ((float) hash->nb / hash->size > 0.85)
350 {
351 fc_lhash_increase_size(hash);
352 }
353 }
354
355 /* (!) search an element in a hash-table */
356 int fc_lhash_lookup(FC_LHash *hash, unsigned long long key,
357 int *val, void **ptr1, void **ptr2)
358 {
359 int index;
360 FC_LHNode *tmp;
361
362 if ((hash == NULL) || (key == 0))
363 return 0;
364
365 /* compute the hash position */
366 index = (unsigned int) (key % hash->size);
367
368 tmp = hash->nodes[index];
369
370 while (tmp != NULL)
371 {
372 if (tmp->key == key)
373 {
374 *val = tmp->value;
375 *ptr1 = tmp->ptr1;
376 *ptr2 = tmp->ptr2;
377 return 1;
378 }
379 tmp = tmp->next;
380 }
381
382 return 0;
383 }
384
385 /* (!) search an element in a hash-table and return pointers
386 on the entries (in order to modify their values without
387 having to remove/modify/insert.
388 WARNING: these pointers are only valid until you perfom
389 an other action on this hash-table. after any
390 operation they may become invalid */
391 int fc_lhash_lookup_modify(FC_LHash *hash, unsigned long long key,
392 int **val, void ***ptr1, void ***ptr2)
393 {
394 int index;
395 FC_LHNode *tmp;
396
397 if ((hash == NULL) || (key == 0))
398 return 0;
399
400 /* compute the hash position */
401 index = (unsigned int) (key % hash->size);
402
403 tmp = hash->nodes[index];
404
405 while (tmp != NULL)
406 {
407 if (tmp->key == key)
408 {
409 *val = &(tmp->value);
410 *ptr1 = &(tmp->ptr1);
411 *ptr2 = &(tmp->ptr2);
412 return 1;
413 }
414 tmp = tmp->next;
415 }
416
417 *val = NULL;
418 *ptr1 = NULL;
419 *ptr2 = NULL;
420 return 0;
421 }
422
423 /* (!) remove an element from a hash-table */
424 void fc_lhash_remove(FC_LHash *hash, unsigned long long key)
425 {
426 unsigned int index;
427 FC_LHNode *tmp, *otmp;
428
429 if ((hash == NULL) || (key == 0))
430 return;
431
432 /* compute the hash position */
433 index = (unsigned int) (key % hash->size);
434
435 otmp = NULL;
436 tmp = hash->nodes[index];
437
438 while (tmp != NULL)
439 {
440 if (tmp->key == key)
441 {
442 /* the old one points to the current next */
443 if (otmp != NULL)
444 {
445 otmp->next = tmp->next;
446 }
447 else
448 {
449 /* the first */
450 hash->nodes[index] = tmp->next;
451 }
452 /* add the node in the free list */
453 tmp->fnext = hash->free_entry;
454 hash->free_entry = tmp;
455 tmp->key = 0;
456 hash->nb--;
457
458 /* done */
459 return;
460 }
461 /* next entry */
462 otmp = tmp;
463 tmp = tmp->next;
464 }
465
466 /* entry not found */
467 }
468
469 /* (!) apply a function to each elements of the hash-table */
470 void fc_lhash_foreach(FC_LHash *hash, FC_LHFunc func, void *data)
471 {
472 int i;
473 FC_LHNode *tmp;
474
475 if ((hash == NULL) || (func == NULL))
476 return;
477
478 /* for each list */
479 for (i = 0; i < hash->size; i++)
480 {
481 tmp = hash->nodes[i];
482 while (tmp != NULL)
483 {
484 (func) (tmp->key, tmp->value, tmp->ptr1,
485 tmp->ptr2, data);
486
487 tmp = tmp->next;
488 }
489 }
490 }
491
492 /* (!) get the number of elements in the hash-table */
493 int fc_lhash_size(FC_LHash *hash)
494 {
495 if (hash == NULL)
496 return (0);
497 return (hash->nb);
498 }