Annotation of embedaddon/quagga/lib/hash.c, revision 1.1.1.2
1.1 misho 1: /* Hash routine.
2: * Copyright (C) 1998 Kunihiro Ishiguro
3: *
4: * This file is part of GNU Zebra.
5: *
6: * GNU Zebra is free software; you can redistribute it and/or modify
7: * it under the terms of the GNU General Public License as published
8: * by the Free Software Foundation; either version 2, or (at your
9: * option) any later version.
10: *
11: * GNU Zebra is distributed in the hope that it will be useful, but
12: * WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: * General Public License for more details.
15: *
16: * You should have received a copy of the GNU General Public License
17: * along with GNU Zebra; see the file COPYING. If not, write to the
18: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19: * Boston, MA 02111-1307, USA.
20: */
21:
22: #include <zebra.h>
23:
24: #include "hash.h"
25: #include "memory.h"
26:
27: /* Allocate a new hash. */
28: struct hash *
29: hash_create_size (unsigned int size, unsigned int (*hash_key) (void *),
30: int (*hash_cmp) (const void *, const void *))
31: {
32: struct hash *hash;
33:
1.1.1.2 ! misho 34: assert ((size & (size-1)) == 0);
1.1 misho 35: hash = XMALLOC (MTYPE_HASH, sizeof (struct hash));
36: hash->index = XCALLOC (MTYPE_HASH_INDEX,
37: sizeof (struct hash_backet *) * size);
38: hash->size = size;
1.1.1.2 ! misho 39: hash->no_expand = 0;
1.1 misho 40: hash->hash_key = hash_key;
41: hash->hash_cmp = hash_cmp;
42: hash->count = 0;
43:
44: return hash;
45: }
46:
47: /* Allocate a new hash with default hash size. */
48: struct hash *
49: hash_create (unsigned int (*hash_key) (void *),
50: int (*hash_cmp) (const void *, const void *))
51: {
1.1.1.2 ! misho 52: return hash_create_size (HASH_INITIAL_SIZE, hash_key, hash_cmp);
1.1 misho 53: }
54:
55: /* Utility function for hash_get(). When this function is specified
56: as alloc_func, return arugment as it is. This function is used for
57: intern already allocated value. */
58: void *
59: hash_alloc_intern (void *arg)
60: {
61: return arg;
62: }
63:
1.1.1.2 ! misho 64: /* Expand hash if the chain length exceeds the threshold. */
! 65: static void hash_expand (struct hash *hash)
! 66: {
! 67: unsigned int i, new_size, losers;
! 68: struct hash_backet *hb, *hbnext, **new_index;
! 69:
! 70: new_size = hash->size * 2;
! 71: new_index = XCALLOC(MTYPE_HASH_INDEX, sizeof(struct hash_backet *) * new_size);
! 72: if (new_index == NULL)
! 73: return;
! 74:
! 75: for (i = 0; i < hash->size; i++)
! 76: for (hb = hash->index[i]; hb; hb = hbnext)
! 77: {
! 78: unsigned int h = hb->key & (new_size - 1);
! 79:
! 80: hbnext = hb->next;
! 81: hb->next = new_index[h];
! 82: new_index[h] = hb;
! 83: }
! 84:
! 85: /* Switch to new table */
! 86: XFREE(MTYPE_HASH_INDEX, hash->index);
! 87: hash->size = new_size;
! 88: hash->index = new_index;
! 89:
! 90: /* Ideally, new index should have chains half as long as the original.
! 91: If expansion didn't help, then not worth expanding again,
! 92: the problem is the hash function. */
! 93: losers = 0;
! 94: for (i = 0; i < hash->size; i++)
! 95: {
! 96: unsigned int len = 0;
! 97: for (hb = hash->index[i]; hb; hb = hb->next)
! 98: {
! 99: if (++len > HASH_THRESHOLD/2)
! 100: ++losers;
! 101: if (len >= HASH_THRESHOLD)
! 102: hash->no_expand = 1;
! 103: }
! 104: }
! 105:
! 106: if (losers > hash->count / 2)
! 107: hash->no_expand = 1;
! 108: }
! 109:
1.1 misho 110: /* Lookup and return hash backet in hash. If there is no
111: corresponding hash backet and alloc_func is specified, create new
112: hash backet. */
113: void *
114: hash_get (struct hash *hash, void *data, void * (*alloc_func) (void *))
115: {
116: unsigned int key;
117: unsigned int index;
118: void *newdata;
1.1.1.2 ! misho 119: unsigned int len;
1.1 misho 120: struct hash_backet *backet;
121:
122: key = (*hash->hash_key) (data);
1.1.1.2 ! misho 123: index = key & (hash->size - 1);
! 124: len = 0;
1.1 misho 125:
1.1.1.2 ! misho 126: for (backet = hash->index[index]; backet != NULL; backet = backet->next)
! 127: {
! 128: if (backet->key == key && (*hash->hash_cmp) (backet->data, data))
! 129: return backet->data;
! 130: ++len;
! 131: }
1.1 misho 132:
133: if (alloc_func)
134: {
135: newdata = (*alloc_func) (data);
136: if (newdata == NULL)
137: return NULL;
138:
1.1.1.2 ! misho 139: if (len > HASH_THRESHOLD && !hash->no_expand)
! 140: {
! 141: hash_expand (hash);
! 142: index = key & (hash->size - 1);
! 143: }
! 144:
1.1 misho 145: backet = XMALLOC (MTYPE_HASH_BACKET, sizeof (struct hash_backet));
146: backet->data = newdata;
147: backet->key = key;
148: backet->next = hash->index[index];
149: hash->index[index] = backet;
150: hash->count++;
151: return backet->data;
152: }
153: return NULL;
154: }
155:
156: /* Hash lookup. */
157: void *
158: hash_lookup (struct hash *hash, void *data)
159: {
160: return hash_get (hash, data, NULL);
161: }
162:
163: /* Simple Bernstein hash which is simple and fast for common case */
164: unsigned int string_hash_make (const char *str)
165: {
166: unsigned int hash = 0;
167:
168: while (*str)
169: hash = (hash * 33) ^ (unsigned int) *str++;
170:
171: return hash;
172: }
173:
174: /* This function release registered value from specified hash. When
175: release is successfully finished, return the data pointer in the
176: hash backet. */
177: void *
178: hash_release (struct hash *hash, void *data)
179: {
180: void *ret;
181: unsigned int key;
182: unsigned int index;
183: struct hash_backet *backet;
184: struct hash_backet *pp;
185:
186: key = (*hash->hash_key) (data);
1.1.1.2 ! misho 187: index = key & (hash->size - 1);
1.1 misho 188:
189: for (backet = pp = hash->index[index]; backet; backet = backet->next)
190: {
191: if (backet->key == key && (*hash->hash_cmp) (backet->data, data))
192: {
193: if (backet == pp)
194: hash->index[index] = backet->next;
195: else
196: pp->next = backet->next;
197:
198: ret = backet->data;
199: XFREE (MTYPE_HASH_BACKET, backet);
200: hash->count--;
201: return ret;
202: }
203: pp = backet;
204: }
205: return NULL;
206: }
207:
208: /* Iterator function for hash. */
209: void
210: hash_iterate (struct hash *hash,
211: void (*func) (struct hash_backet *, void *), void *arg)
212: {
213: unsigned int i;
214: struct hash_backet *hb;
215: struct hash_backet *hbnext;
216:
217: for (i = 0; i < hash->size; i++)
218: for (hb = hash->index[i]; hb; hb = hbnext)
219: {
220: /* get pointer to next hash backet here, in case (*func)
221: * decides to delete hb by calling hash_release
222: */
223: hbnext = hb->next;
224: (*func) (hb, arg);
225: }
226: }
227:
228: /* Clean up hash. */
229: void
230: hash_clean (struct hash *hash, void (*free_func) (void *))
231: {
232: unsigned int i;
233: struct hash_backet *hb;
234: struct hash_backet *next;
235:
236: for (i = 0; i < hash->size; i++)
237: {
238: for (hb = hash->index[i]; hb; hb = next)
239: {
240: next = hb->next;
241:
242: if (free_func)
243: (*free_func) (hb->data);
244:
245: XFREE (MTYPE_HASH_BACKET, hb);
246: hash->count--;
247: }
248: hash->index[i] = NULL;
249: }
250: }
251:
252: /* Free hash memory. You may call hash_clean before call this
253: function. */
254: void
255: hash_free (struct hash *hash)
256: {
257: XFREE (MTYPE_HASH_INDEX, hash->index);
258: XFREE (MTYPE_HASH, hash);
259: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>