]>
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. */
32 struct hash
*hash_create_size(unsigned int size
,
33 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
));
41 XCALLOC(MTYPE_HASH_INDEX
, 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. */
52 struct hash
*hash_create(unsigned int (*hash_key
)(void *),
53 int (*hash_cmp
)(const void *, const void *))
55 return hash_create_size(HASH_INITIAL_SIZE
, hash_key
, hash_cmp
);
58 /* Utility function for hash_get(). When this function is specified
59 as alloc_func, return arugment as it is. This function is used for
60 intern already allocated value. */
61 void *hash_alloc_intern(void *arg
)
66 /* Expand hash if the chain length exceeds the threshold. */
67 static void hash_expand(struct hash
*hash
)
69 unsigned int i
, new_size
, losers
;
70 struct hash_backet
*hb
, *hbnext
, **new_index
;
72 new_size
= hash
->size
* 2;
73 new_index
= XCALLOC(MTYPE_HASH_INDEX
,
74 sizeof(struct hash_backet
*) * new_size
);
75 if (new_index
== NULL
)
78 for (i
= 0; i
< hash
->size
; i
++)
79 for (hb
= hash
->index
[i
]; hb
; hb
= hbnext
) {
80 unsigned int h
= hb
->key
& (new_size
- 1);
83 hb
->next
= new_index
[h
];
87 /* Switch to new table */
88 XFREE(MTYPE_HASH_INDEX
, hash
->index
);
89 hash
->size
= new_size
;
90 hash
->index
= new_index
;
92 /* Ideally, new index should have chains half as long as the original.
93 If expansion didn't help, then not worth expanding again,
94 the problem is the hash function. */
96 for (i
= 0; i
< hash
->size
; i
++) {
98 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
99 if (++len
> HASH_THRESHOLD
/ 2)
101 if (len
>= HASH_THRESHOLD
)
106 if (losers
> hash
->count
/ 2)
110 /* Lookup and return hash backet in hash. If there is no
111 corresponding hash backet and alloc_func is specified, create new
113 void *hash_get(struct hash
*hash
, void *data
, void *(*alloc_func
)(void *))
119 struct hash_backet
*backet
;
121 key
= (*hash
->hash_key
)(data
);
122 index
= key
& (hash
->size
- 1);
125 for (backet
= hash
->index
[index
]; backet
!= NULL
;
126 backet
= backet
->next
) {
127 if (backet
->key
== key
&& (*hash
->hash_cmp
)(backet
->data
, data
))
133 newdata
= (*alloc_func
)(data
);
137 if (len
> HASH_THRESHOLD
&& !hash
->no_expand
) {
139 index
= key
& (hash
->size
- 1);
142 backet
= XMALLOC(MTYPE_HASH_BACKET
, sizeof(struct hash_backet
));
143 backet
->data
= newdata
;
145 backet
->next
= hash
->index
[index
];
146 hash
->index
[index
] = backet
;
154 void *hash_lookup(struct hash
*hash
, void *data
)
156 return hash_get(hash
, data
, NULL
);
159 /* Simple Bernstein hash which is simple and fast for common case */
160 unsigned int string_hash_make(const char *str
)
162 unsigned int hash
= 0;
165 hash
= (hash
* 33) ^ (unsigned int)*str
++;
170 /* This function release registered value from specified hash. When
171 release is successfully finished, return the data pointer in the
173 void *hash_release(struct hash
*hash
, void *data
)
178 struct hash_backet
*backet
;
179 struct hash_backet
*pp
;
181 key
= (*hash
->hash_key
)(data
);
182 index
= key
& (hash
->size
- 1);
184 for (backet
= pp
= hash
->index
[index
]; backet
; backet
= backet
->next
) {
185 if (backet
->key
== key
186 && (*hash
->hash_cmp
)(backet
->data
, data
)) {
188 hash
->index
[index
] = backet
->next
;
190 pp
->next
= backet
->next
;
193 XFREE(MTYPE_HASH_BACKET
, backet
);
202 /* Iterator function for hash. */
203 void hash_iterate(struct hash
*hash
, void (*func
)(struct hash_backet
*, void *),
207 struct hash_backet
*hb
;
208 struct hash_backet
*hbnext
;
210 for (i
= 0; i
< hash
->size
; i
++)
211 for (hb
= hash
->index
[i
]; hb
; hb
= hbnext
) {
212 /* get pointer to next hash backet here, in case (*func)
213 * decides to delete hb by calling hash_release
220 /* Iterator function for hash. */
221 void hash_walk(struct hash
*hash
, int (*func
)(struct hash_backet
*, void *),
225 struct hash_backet
*hb
;
226 struct hash_backet
*hbnext
;
227 int ret
= HASHWALK_CONTINUE
;
229 for (i
= 0; i
< hash
->size
; i
++) {
230 for (hb
= hash
->index
[i
]; hb
; hb
= hbnext
) {
231 /* get pointer to next hash backet here, in case (*func)
232 * decides to delete hb by calling hash_release
235 ret
= (*func
)(hb
, arg
);
236 if (ret
== HASHWALK_ABORT
)
243 void hash_clean(struct hash
*hash
, void (*free_func
)(void *))
246 struct hash_backet
*hb
;
247 struct hash_backet
*next
;
249 for (i
= 0; i
< hash
->size
; i
++) {
250 for (hb
= hash
->index
[i
]; hb
; hb
= next
) {
254 (*free_func
)(hb
->data
);
256 XFREE(MTYPE_HASH_BACKET
, hb
);
259 hash
->index
[i
] = NULL
;
263 /* Free hash memory. You may call hash_clean before call this
265 void hash_free(struct hash
*hash
)
267 XFREE(MTYPE_HASH_INDEX
, hash
->index
);
268 XFREE(MTYPE_HASH
, hash
);