]>
git.proxmox.com Git - mirror_frr.git/blob - lib/hash.c
2 * Copyright (C) 1998 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
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.
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.
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.
27 DEFINE_MTYPE( LIB
, HASH
, "Hash")
28 DEFINE_MTYPE( LIB
, HASH_BACKET
, "Hash Bucket")
29 DEFINE_MTYPE_STATIC(LIB
, HASH_INDEX
, "Hash Index")
31 /* Allocate a new hash. */
33 hash_create_size (unsigned int size
, unsigned int (*hash_key
) (void *),
34 int (*hash_cmp
) (const void *, const void *))
38 assert ((size
& (size
-1)) == 0);
39 hash
= XMALLOC (MTYPE_HASH
, sizeof (struct hash
));
40 hash
->index
= XCALLOC (MTYPE_HASH_INDEX
,
41 sizeof (struct hash_backet
*) * size
);
44 hash
->hash_key
= hash_key
;
45 hash
->hash_cmp
= hash_cmp
;
51 /* Allocate a new hash with default hash size. */
53 hash_create (unsigned int (*hash_key
) (void *),
54 int (*hash_cmp
) (const void *, const void *))
56 return hash_create_size (HASH_INITIAL_SIZE
, hash_key
, hash_cmp
);
59 /* Utility function for hash_get(). When this function is specified
60 as alloc_func, return arugment as it is. This function is used for
61 intern already allocated value. */
63 hash_alloc_intern (void *arg
)
68 /* Expand hash if the chain length exceeds the threshold. */
69 static void hash_expand (struct hash
*hash
)
71 unsigned int i
, new_size
, losers
;
72 struct hash_backet
*hb
, *hbnext
, **new_index
;
74 new_size
= hash
->size
* 2;
75 new_index
= XCALLOC(MTYPE_HASH_INDEX
, sizeof(struct hash_backet
*) * new_size
);
76 if (new_index
== NULL
)
79 for (i
= 0; i
< hash
->size
; i
++)
80 for (hb
= hash
->index
[i
]; hb
; hb
= hbnext
)
82 unsigned int h
= hb
->key
& (new_size
- 1);
85 hb
->next
= new_index
[h
];
89 /* Switch to new table */
90 XFREE(MTYPE_HASH_INDEX
, hash
->index
);
91 hash
->size
= new_size
;
92 hash
->index
= new_index
;
94 /* Ideally, new index should have chains half as long as the original.
95 If expansion didn't help, then not worth expanding again,
96 the problem is the hash function. */
98 for (i
= 0; i
< hash
->size
; i
++)
100 unsigned int len
= 0;
101 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
)
103 if (++len
> HASH_THRESHOLD
/2)
105 if (len
>= HASH_THRESHOLD
)
110 if (losers
> hash
->count
/ 2)
114 /* Lookup and return hash backet in hash. If there is no
115 corresponding hash backet and alloc_func is specified, create new
118 hash_get (struct hash
*hash
, void *data
, void * (*alloc_func
) (void *))
124 struct hash_backet
*backet
;
126 key
= (*hash
->hash_key
) (data
);
127 index
= key
& (hash
->size
- 1);
130 for (backet
= hash
->index
[index
]; backet
!= NULL
; backet
= backet
->next
)
132 if (backet
->key
== key
&& (*hash
->hash_cmp
) (backet
->data
, data
))
139 newdata
= (*alloc_func
) (data
);
143 if (len
> HASH_THRESHOLD
&& !hash
->no_expand
)
146 index
= key
& (hash
->size
- 1);
149 backet
= XMALLOC (MTYPE_HASH_BACKET
, sizeof (struct hash_backet
));
150 backet
->data
= newdata
;
152 backet
->next
= hash
->index
[index
];
153 hash
->index
[index
] = backet
;
162 hash_lookup (struct hash
*hash
, void *data
)
164 return hash_get (hash
, data
, NULL
);
167 /* Simple Bernstein hash which is simple and fast for common case */
168 unsigned int string_hash_make (const char *str
)
170 unsigned int hash
= 0;
173 hash
= (hash
* 33) ^ (unsigned int) *str
++;
178 /* This function release registered value from specified hash. When
179 release is successfully finished, return the data pointer in the
182 hash_release (struct hash
*hash
, void *data
)
187 struct hash_backet
*backet
;
188 struct hash_backet
*pp
;
190 key
= (*hash
->hash_key
) (data
);
191 index
= key
& (hash
->size
- 1);
193 for (backet
= pp
= hash
->index
[index
]; backet
; backet
= backet
->next
)
195 if (backet
->key
== key
&& (*hash
->hash_cmp
) (backet
->data
, data
))
198 hash
->index
[index
] = backet
->next
;
200 pp
->next
= backet
->next
;
203 XFREE (MTYPE_HASH_BACKET
, backet
);
212 /* Iterator function for hash. */
214 hash_iterate (struct hash
*hash
,
215 void (*func
) (struct hash_backet
*, void *), void *arg
)
218 struct hash_backet
*hb
;
219 struct hash_backet
*hbnext
;
221 for (i
= 0; i
< hash
->size
; i
++)
222 for (hb
= hash
->index
[i
]; hb
; hb
= hbnext
)
224 /* get pointer to next hash backet here, in case (*func)
225 * decides to delete hb by calling hash_release
232 /* Iterator function for hash. */
234 hash_walk (struct hash
*hash
,
235 int (*func
) (struct hash_backet
*, void *), void *arg
)
238 struct hash_backet
*hb
;
239 struct hash_backet
*hbnext
;
240 int ret
= HASHWALK_CONTINUE
;
242 for (i
= 0; i
< hash
->size
; i
++)
244 for (hb
= hash
->index
[i
]; hb
; hb
= hbnext
)
246 /* get pointer to next hash backet here, in case (*func)
247 * decides to delete hb by calling hash_release
250 ret
= (*func
) (hb
, arg
);
251 if (ret
== HASHWALK_ABORT
)
259 hash_clean (struct hash
*hash
, void (*free_func
) (void *))
262 struct hash_backet
*hb
;
263 struct hash_backet
*next
;
265 for (i
= 0; i
< hash
->size
; i
++)
267 for (hb
= hash
->index
[i
]; hb
; hb
= next
)
272 (*free_func
) (hb
->data
);
274 XFREE (MTYPE_HASH_BACKET
, hb
);
277 hash
->index
[i
] = NULL
;
281 /* Free hash memory. You may call hash_clean before call this
284 hash_free (struct hash
*hash
)
286 XFREE (MTYPE_HASH_INDEX
, hash
->index
);
287 XFREE (MTYPE_HASH
, hash
);