]>
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 along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 DEFINE_MTYPE( LIB
, HASH
, "Hash")
27 DEFINE_MTYPE( LIB
, HASH_BACKET
, "Hash Bucket")
28 DEFINE_MTYPE_STATIC(LIB
, HASH_INDEX
, "Hash Index")
30 /* Allocate a new hash. */
32 hash_create_size (unsigned int size
, unsigned int (*hash_key
) (void *),
33 int (*hash_cmp
) (const void *, const void *))
37 assert ((size
& (size
-1)) == 0);
38 hash
= XMALLOC (MTYPE_HASH
, sizeof (struct hash
));
39 hash
->index
= XCALLOC (MTYPE_HASH_INDEX
,
40 sizeof (struct hash_backet
*) * size
);
43 hash
->hash_key
= hash_key
;
44 hash
->hash_cmp
= hash_cmp
;
50 /* Allocate a new hash with default hash size. */
52 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. */
62 hash_alloc_intern (void *arg
)
67 /* Expand hash if the chain length exceeds the threshold. */
68 static void hash_expand (struct hash
*hash
)
70 unsigned int i
, new_size
, losers
;
71 struct hash_backet
*hb
, *hbnext
, **new_index
;
73 new_size
= hash
->size
* 2;
74 new_index
= XCALLOC(MTYPE_HASH_INDEX
, 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
)
81 unsigned int h
= hb
->key
& (new_size
- 1);
84 hb
->next
= new_index
[h
];
88 /* Switch to new table */
89 XFREE(MTYPE_HASH_INDEX
, hash
->index
);
90 hash
->size
= new_size
;
91 hash
->index
= new_index
;
93 /* Ideally, new index should have chains half as long as the original.
94 If expansion didn't help, then not worth expanding again,
95 the problem is the hash function. */
97 for (i
= 0; i
< hash
->size
; i
++)
100 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
)
102 if (++len
> HASH_THRESHOLD
/2)
104 if (len
>= HASH_THRESHOLD
)
109 if (losers
> hash
->count
/ 2)
113 /* Lookup and return hash backet in hash. If there is no
114 corresponding hash backet and alloc_func is specified, create new
117 hash_get (struct hash
*hash
, void *data
, void * (*alloc_func
) (void *))
123 struct hash_backet
*backet
;
125 key
= (*hash
->hash_key
) (data
);
126 index
= key
& (hash
->size
- 1);
129 for (backet
= hash
->index
[index
]; backet
!= NULL
; backet
= backet
->next
)
131 if (backet
->key
== key
&& (*hash
->hash_cmp
) (backet
->data
, data
))
138 newdata
= (*alloc_func
) (data
);
142 if (len
> HASH_THRESHOLD
&& !hash
->no_expand
)
145 index
= key
& (hash
->size
- 1);
148 backet
= XMALLOC (MTYPE_HASH_BACKET
, sizeof (struct hash_backet
));
149 backet
->data
= newdata
;
151 backet
->next
= hash
->index
[index
];
152 hash
->index
[index
] = backet
;
161 hash_lookup (struct hash
*hash
, void *data
)
163 return hash_get (hash
, data
, NULL
);
166 /* Simple Bernstein hash which is simple and fast for common case */
167 unsigned int string_hash_make (const char *str
)
169 unsigned int hash
= 0;
172 hash
= (hash
* 33) ^ (unsigned int) *str
++;
177 /* This function release registered value from specified hash. When
178 release is successfully finished, return the data pointer in the
181 hash_release (struct hash
*hash
, void *data
)
186 struct hash_backet
*backet
;
187 struct hash_backet
*pp
;
189 key
= (*hash
->hash_key
) (data
);
190 index
= key
& (hash
->size
- 1);
192 for (backet
= pp
= hash
->index
[index
]; backet
; backet
= backet
->next
)
194 if (backet
->key
== key
&& (*hash
->hash_cmp
) (backet
->data
, data
))
197 hash
->index
[index
] = backet
->next
;
199 pp
->next
= backet
->next
;
202 XFREE (MTYPE_HASH_BACKET
, backet
);
211 /* Iterator function for hash. */
213 hash_iterate (struct hash
*hash
,
214 void (*func
) (struct hash_backet
*, void *), void *arg
)
217 struct hash_backet
*hb
;
218 struct hash_backet
*hbnext
;
220 for (i
= 0; i
< hash
->size
; i
++)
221 for (hb
= hash
->index
[i
]; hb
; hb
= hbnext
)
223 /* get pointer to next hash backet here, in case (*func)
224 * decides to delete hb by calling hash_release
231 /* Iterator function for hash. */
233 hash_walk (struct hash
*hash
,
234 int (*func
) (struct hash_backet
*, void *), void *arg
)
237 struct hash_backet
*hb
;
238 struct hash_backet
*hbnext
;
239 int ret
= HASHWALK_CONTINUE
;
241 for (i
= 0; i
< hash
->size
; i
++)
243 for (hb
= hash
->index
[i
]; hb
; hb
= hbnext
)
245 /* get pointer to next hash backet here, in case (*func)
246 * decides to delete hb by calling hash_release
249 ret
= (*func
) (hb
, arg
);
250 if (ret
== HASHWALK_ABORT
)
258 hash_clean (struct hash
*hash
, void (*free_func
) (void *))
261 struct hash_backet
*hb
;
262 struct hash_backet
*next
;
264 for (i
= 0; i
< hash
->size
; i
++)
266 for (hb
= hash
->index
[i
]; hb
; hb
= next
)
271 (*free_func
) (hb
->data
);
273 XFREE (MTYPE_HASH_BACKET
, hb
);
276 hash
->index
[i
] = NULL
;
280 /* Free hash memory. You may call hash_clean before call this
283 hash_free (struct hash
*hash
)
285 XFREE (MTYPE_HASH_INDEX
, hash
->index
);
286 XFREE (MTYPE_HASH
, hash
);