1 /***********************************************************************
5 * Implementation of hash tables. Each item inserted must include
6 * a hash_bucket member.
8 * Copyright (C) 2002 Roaring Penguin Software Inc.
10 * This software may be distributed under the terms of the GNU General
11 * Public License, Version 2 or (at your option) any later version.
15 ***********************************************************************/
17 static char const RCSID
[] =
18 "$Id: hash.c,v 1.1.48.1 2005/08/08 12:05:25 honor Exp $";
23 #define BITS_IN_int ( sizeof(int) * CHAR_BIT )
24 #define THREE_QUARTERS ((int) ((BITS_IN_int * 3) / 4))
25 #define ONE_EIGHTH ((int) (BITS_IN_int / 8))
26 #define HIGH_BITS ( ~((unsigned int)(~0) >> ONE_EIGHTH ))
28 #define GET_BUCKET(tab, data) ((hash_bucket *) ((char *) (data) + (tab)->hash_offset))
30 #define GET_ITEM(tab, bucket) ((void *) (((char *) (void *) bucket) - (tab)->hash_offset))
32 static void *hash_next_cursor(hash_table
*tab
, hash_bucket
*b
);
34 /**********************************************************************
35 * %FUNCTION: hash_init
38 * hash_offset -- offset of hash_bucket data member in inserted items
39 * compute -- pointer to function to compute hash value
40 * compare -- pointer to comparison function. Returns 0 if items are equal,
45 * Initializes a hash table.
46 ***********************************************************************/
48 hash_init(hash_table
*tab
,
50 unsigned int (*compute
)(void *data
),
51 int (*compare
)(void *item1
, void *item2
))
55 tab
->hash_offset
= hash_offset
;
56 tab
->compute_hash
= compute
;
57 tab
->compare
= compare
;
58 for (i
=0; i
<HASHTAB_SIZE
; i
++) {
59 tab
->buckets
[i
] = NULL
;
64 /**********************************************************************
65 * %FUNCTION: hash_insert
67 * tab -- hash table to insert into
68 * item -- the item we're inserting
72 * Inserts an item into the hash table. It must not currently be in any
74 ***********************************************************************/
76 hash_insert(hash_table
*tab
,
79 hash_bucket
*b
= GET_BUCKET(tab
, item
);
80 unsigned int val
= tab
->compute_hash(item
);
84 b
->next
= tab
->buckets
[val
];
88 tab
->buckets
[val
] = b
;
92 /**********************************************************************
93 * %FUNCTION: hash_remove
96 * item -- item in hash table
100 * Removes item from hash table
101 ***********************************************************************/
103 hash_remove(hash_table
*tab
,
106 hash_bucket
*b
= GET_BUCKET(tab
, item
);
107 unsigned int val
= b
->hashval
% HASHTAB_SIZE
;
110 b
->prev
->next
= b
->next
;
112 tab
->buckets
[val
] = b
->next
;
115 b
->next
->prev
= b
->prev
;
120 /**********************************************************************
121 * %FUNCTION: hash_find
124 * item -- item equal to one we're seeking (in the compare-function sense)
126 * A pointer to the item in the hash table, or NULL if no such item
128 * Searches hash table for item.
129 ***********************************************************************/
131 hash_find(hash_table
*tab
,
134 unsigned int val
= tab
->compute_hash(item
) % HASHTAB_SIZE
;
136 for (b
= tab
->buckets
[val
]; b
; b
= b
->next
) {
137 void *item2
= GET_ITEM(tab
, b
);
138 if (!tab
->compare(item
, item2
)) return item2
;
143 /**********************************************************************
144 * %FUNCTION: hash_find_next
147 * item -- an item returned by hash_find or hash_find_next
149 * A pointer to the next equal item in the hash table, or NULL if no such item
151 * Searches hash table for anoter item equivalent to this one. Search
153 ***********************************************************************/
155 hash_find_next(hash_table
*tab
,
158 hash_bucket
*b
= GET_BUCKET(tab
, item
);
159 for (b
= b
->next
; b
; b
= b
->next
) {
160 void *item2
= GET_ITEM(tab
, b
);
161 if (!tab
->compare(item
, item2
)) return item2
;
165 /**********************************************************************
166 * %FUNCTION: hash_start
169 * cursor -- a void pointer to keep track of location
171 * "first" entry in hash table, or NULL if table is empty
173 * Starts an iterator -- sets cursor so hash_next will return next entry.
174 ***********************************************************************/
176 hash_start(hash_table
*tab
, void **cursor
)
179 for (i
=0; i
<HASHTAB_SIZE
; i
++) {
180 if (tab
->buckets
[i
]) {
181 /* Point cursor to NEXT item so it is valid
182 even if current item is free'd */
183 *cursor
= hash_next_cursor(tab
, tab
->buckets
[i
]);
184 return GET_ITEM(tab
, tab
->buckets
[i
]);
191 /**********************************************************************
192 * %FUNCTION: hash_next
195 * cursor -- cursor into hash table
197 * Next item in table, or NULL.
199 * Steps cursor to next item in table.
200 ***********************************************************************/
202 hash_next(hash_table
*tab
, void **cursor
)
206 if (!*cursor
) return NULL
;
208 b
= (hash_bucket
*) *cursor
;
209 *cursor
= hash_next_cursor(tab
, b
);
210 return GET_ITEM(tab
, b
);
213 /**********************************************************************
214 * %FUNCTION: hash_next_cursor
216 * tab -- a hash table
219 * Cursor value for bucket following b in hash table.
220 ***********************************************************************/
222 hash_next_cursor(hash_table
*tab
, hash_bucket
*b
)
226 if (b
->next
) return b
->next
;
228 i
= b
->hashval
% HASHTAB_SIZE
;
229 for (++i
; i
<HASHTAB_SIZE
; ++i
) {
230 if (tab
->buckets
[i
]) return tab
->buckets
[i
];
236 hash_num_entries(hash_table
*tab
)
238 return tab
->num_entries
;
241 /**********************************************************************
242 * %FUNCTION: hash_pjw
244 * str -- a zero-terminated string
246 * A hash value using the hashpjw algorithm
248 * An adaptation of Peter Weinberger's (PJW) generic hashing
249 * algorithm based on Allen Holub's version. Accepts a pointer
250 * to a datum to be hashed and returns an unsigned integer.
251 ***********************************************************************/
253 hash_pjw(char const * str
)
255 unsigned int hash_value
, i
;
257 for (hash_value
= 0; *str
; ++str
) {
258 hash_value
= ( hash_value
<< ONE_EIGHTH
) + *str
;
259 if (( i
= hash_value
& HIGH_BITS
) != 0 ) {
261 ( hash_value
^ ( i
>> THREE_QUARTERS
)) &