source: trunk/src/kmk/hash.h@ 1861

Last change on this file since 1861 was 1858, checked in by bird, 17 years ago

kmk: Added hash_find_slot_prehashed for the benefit of the strcache and includedep.

  • Property svn:eol-style set to native
File size: 11.4 KB
Line 
1/* hash.h -- decls for hash table
2Copyright (C) 1995, 1999, 2002 Free Software Foundation, Inc.
3Written by Greg McGary <gkm@gnu.org> <greg@mcgary.org>
4
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation; either version 2, or (at your option)
8any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License along with
16this program; see the file COPYING. If not, write to the Free Software
17Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */
18
19#ifndef _hash_h_
20#define _hash_h_
21
22#include <stdio.h>
23#include <ctype.h>
24
25#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
26# if !defined __GLIBC__ || !defined __P
27# undef __P
28# define __P(protos) protos
29# endif
30#else /* Not C++ or ANSI C. */
31# undef __P
32# define __P(protos) ()
33/* We can get away without defining `const' here only because in this file
34 it is used only inside the prototype for `fnmatch', which is elided in
35 non-ANSI C where `const' is problematical. */
36#endif /* C++ or ANSI C. */
37
38typedef unsigned long (*hash_func_t) __P((void const *key));
39typedef int (*hash_cmp_func_t) __P((void const *x, void const *y));
40typedef void (*hash_map_func_t) __P((void const *item));
41typedef void (*hash_map_arg_func_t) __P((void const *item, void *arg));
42
43struct hash_table
44{
45 void **ht_vec;
46 unsigned long ht_size; /* total number of slots (power of 2) */
47 unsigned long ht_capacity; /* usable slots, limited by loading-factor */
48 unsigned long ht_fill; /* items in table */
49 unsigned long ht_empty_slots; /* empty slots not including deleted slots */
50 unsigned long ht_collisions; /* # of failed calls to comparison function */
51 unsigned long ht_lookups; /* # of queries */
52 unsigned int ht_rehashes; /* # of times we've expanded table */
53 hash_func_t ht_hash_1; /* primary hash function */
54 hash_func_t ht_hash_2; /* secondary hash function */
55 hash_cmp_func_t ht_compare; /* comparison function */
56};
57
58typedef int (*qsort_cmp_t) __P((void const *, void const *));
59
60void hash_init __P((struct hash_table *ht, unsigned long size,
61 hash_func_t hash_1, hash_func_t hash_2, hash_cmp_func_t hash_cmp));
62void hash_load __P((struct hash_table *ht, void *item_table,
63 unsigned long cardinality, unsigned long size));
64void **hash_find_slot __P((struct hash_table *ht, void const *key));
65#ifdef CONFIG_WITH_VALUE_LENGTH
66void **hash_find_slot_prehashed __P((struct hash_table *ht, const void *key,
67 unsigned int hash_1, unsigned int hash_2));
68#endif
69void *hash_find_item __P((struct hash_table *ht, void const *key));
70void *hash_insert __P((struct hash_table *ht, const void *item));
71void *hash_insert_at __P((struct hash_table *ht, const void *item, void const *slot));
72void *hash_delete __P((struct hash_table *ht, void const *item));
73void *hash_delete_at __P((struct hash_table *ht, void const *slot));
74void hash_delete_items __P((struct hash_table *ht));
75void hash_free_items __P((struct hash_table *ht));
76void hash_free __P((struct hash_table *ht, int free_items));
77void hash_map __P((struct hash_table *ht, hash_map_func_t map));
78void hash_map_arg __P((struct hash_table *ht, hash_map_arg_func_t map, void *arg));
79void hash_print_stats __P((struct hash_table *ht, FILE *out_FILE));
80void **hash_dump __P((struct hash_table *ht, void **vector_0, qsort_cmp_t compare));
81
82extern void *hash_deleted_item;
83#define HASH_VACANT(item) ((item) == 0 || (void *) (item) == hash_deleted_item)
84
85
86
87/* hash and comparison macros for case-sensitive string keys. */
88
89#ifndef CONFIG_WITH_OPTIMIZATION_HACKS
90#define STRING_HASH_1(KEY, RESULT) do { \
91 unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
92 while (*++_key_) \
93 (RESULT) += (*_key_ << (_key_[1] & 0xf)); \
94} while (0)
95#else /* CONFIG_WITH_OPTIMIZATION_HACKS */
96# define STRING_HASH_1(KEY, RESULT) do { \
97 unsigned char const *_key_ = (unsigned char const *) (KEY); \
98 unsigned int _ch_ = *_key_; \
99 while (_ch_) \
100 { \
101 unsigned char _ch2_ = *++_key_; \
102 (RESULT) += (_ch_ << (_ch2_ & 0xf)); \
103 _ch_ = _ch2_; \
104 } \
105} while (0)
106#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
107#define return_STRING_HASH_1(KEY) do { \
108 unsigned long _result_ = 0; \
109 STRING_HASH_1 ((KEY), _result_); \
110 return _result_; \
111} while (0)
112
113#ifndef CONFIG_WITH_OPTIMIZATION_HACKS
114#define STRING_HASH_2(KEY, RESULT) do { \
115 unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
116 while (*++_key_) \
117 (RESULT) += (*_key_ << (_key_[1] & 0x7)); \
118} while (0)
119#else /* CONFIG_WITH_OPTIMIZATION_HACKS */
120# define STRING_HASH_2(KEY, RESULT) do { \
121 unsigned char const *_key_ = (unsigned char const *) (KEY); \
122 unsigned int _ch_ = *_key_; \
123 while (_ch_) \
124 { \
125 unsigned char _ch2_ = *++_key_; \
126 (RESULT) += (_ch_ << (_ch2_ & 0x7)); \
127 _ch_ = _ch2_; \
128 } \
129} while (0)
130#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
131#define return_STRING_HASH_2(KEY) do { \
132 unsigned long _result_ = 0; \
133 STRING_HASH_2 ((KEY), _result_); \
134 return _result_; \
135} while (0)
136
137#define STRING_COMPARE(X, Y, RESULT) do { \
138 RESULT = strcmp ((X), (Y)); \
139} while (0)
140#define return_STRING_COMPARE(X, Y) do { \
141 return strcmp ((X), (Y)); \
142} while (0)
143
144#ifndef CONFIG_WITH_OPTIMIZATION_HACKS
145#define STRING_N_HASH_1(KEY, N, RESULT) do { \
146 unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
147 int _n_ = (N); \
148 if (_n_) \
149 while (--_n_ && *++_key_) \
150 (RESULT) += (*_key_ << (_key_[1] & 0xf)); \
151 (RESULT) += *++_key_; \
152} while (0)
153#else /* CONFIG_WITH_OPTIMIZATION_HACKS */
154# define STRING_N_HASH_1(KEY, N, RESULT) do { \
155 unsigned char const *_key_ = (unsigned char const *) (KEY); \
156 unsigned int _ch_ = *_key_; \
157 int _n_ = (N); \
158 if (_n_) \
159 { \
160 for (;;) \
161 { \
162 unsigned char _ch2_; \
163 if (!--_n_) \
164 { \
165 (RESULT) += _ch_; \
166 break; \
167 } \
168 _ch2_ = *++_key_; \
169 (RESULT) += (_ch_ << (_ch2_ & 0xf)); \
170 _ch_ = _ch2_; \
171 if (!_ch_) break; \
172 } \
173 } \
174 else \
175 (RESULT) += _ch_; \
176} while (0)
177#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
178#define return_STRING_N_HASH_1(KEY, N) do { \
179 unsigned long _result_ = 0; \
180 STRING_N_HASH_1 ((KEY), (N), _result_); \
181 return _result_; \
182} while (0)
183
184#ifndef CONFIG_WITH_OPTIMIZATION_HACKS
185#define STRING_N_HASH_2(KEY, N, RESULT) do { \
186 unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
187 int _n_ = (N); \
188 if (_n_) \
189 while (--_n_ && *++_key_) \
190 (RESULT) += (*_key_ << (_key_[1] & 0x7)); \
191 (RESULT) += *++_key_; \
192} while (0)
193#else /* CONFIG_WITH_OPTIMIZATION_HACKS */
194# define STRING_N_HASH_2(KEY, N, RESULT) do { \
195 unsigned char const *_key_ = (unsigned char const *) (KEY); \
196 unsigned int _ch_ = *_key_; \
197 int _n_ = (N); \
198 if (_n_) \
199 { \
200 for (;;) \
201 { \
202 unsigned char _ch2_; \
203 if (!--_n_) \
204 { \
205 (RESULT) += _ch_; \
206 break; \
207 } \
208 _ch2_ = *++_key_; \
209 (RESULT) += (_ch_ << (_ch2_ & 0x7)); \
210 _ch_ = _ch2_; \
211 if (!_ch_) break; \
212 } \
213 } \
214 else \
215 (RESULT) += _ch_; \
216} while (0)
217#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
218#define return_STRING_N_HASH_2(KEY, N) do { \
219 unsigned long _result_ = 0; \
220 STRING_N_HASH_2 ((KEY), (N), _result_); \
221 return _result_; \
222} while (0)
223
224#define STRING_N_COMPARE(X, Y, N, RESULT) do { \
225 RESULT = strncmp ((X), (Y), (N)); \
226} while (0)
227#define return_STRING_N_COMPARE(X, Y, N) do { \
228 return strncmp ((X), (Y), (N)); \
229} while (0)
230
231#ifdef HAVE_CASE_INSENSITIVE_FS
232
233/* hash and comparison macros for case-insensitive string _key_s. */
234
235#if 1 /*ndef CONFIG_WITH_OPTIMIZATION_HACKS - testme */
236#define ISTRING_HASH_1(KEY, RESULT) do { \
237 unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
238 while (*++_key_) \
239 (RESULT) += ((isupper (*_key_) ? tolower (*_key_) : *_key_) << (_key_[1] & 0xf)); \
240} while (0)
241#else /* CONFIG_WITH_OPTIMIZATION_HACKS */
242#define ISTRING_HASH_1(KEY, RESULT) do { \
243 unsigned char const *_key_ = (unsigned char const *) (KEY); \
244 unsigned int _ch_ = *_key_;
245 while (_ch_) \
246 { \
247 unsigned _ch2_ = *++_key_; \
248 (RESULT) += ((isupper (_ch_) ? tolower (_ch_) : _ch_) << (_ch2_ & 0xf)); \
249 _ch_ = _ch2_; \
250 } \
251} while (0)
252#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
253#define return_ISTRING_HASH_1(KEY) do { \
254 unsigned long _result_ = 0; \
255 ISTRING_HASH_1 ((KEY), _result_); \
256 return _result_; \
257} while (0)
258
259#if 1 /* ndef CONFIG_WITH_OPTIMIZATION_HACKS - testme */
260#define ISTRING_HASH_2(KEY, RESULT) do { \
261 unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
262 while (*++_key_) \
263 (RESULT) += ((isupper (*_key_) ? tolower (*_key_) : *_key_) << (_key_[1] & 0x7)); \
264} while (0)
265#else /* CONFIG_WITH_OPTIMIZATION_HACKS */
266#define ISTRING_HASH_2(KEY, RESULT) do { \
267 unsigned char const *_key_ = (unsigned char const *) (KEY); \
268 unsigned int _ch_ = *_key_;
269 while (_ch_) \
270 { \
271 unsigned _ch2_ = *++_key_; \
272 (RESULT) += ((isupper (_ch_) ? tolower (_ch_) : _ch_) << (_ch2_ & 0x7)); \
273 _ch_ = _ch2_; \
274 } \
275} while (0)
276#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
277#define return_ISTRING_HASH_2(KEY) do { \
278 unsigned long _result_ = 0; \
279 ISTRING_HASH_2 ((KEY), _result_); \
280 return _result_; \
281} while (0)
282
283#define ISTRING_COMPARE(X, Y, RESULT) do { \
284 RESULT = strcasecmp ((X), (Y)); \
285} while (0)
286#define return_ISTRING_COMPARE(X, Y) do { \
287 return strcasecmp ((X), (Y)); \
288} while (0)
289
290#else
291
292#define ISTRING_HASH_1(KEY, RESULT) STRING_HASH_1 ((KEY), (RESULT))
293#define return_ISTRING_HASH_1(KEY) return_STRING_HASH_1 (KEY)
294
295#define ISTRING_HASH_2(KEY, RESULT) STRING_HASH_2 ((KEY), (RESULT))
296#define return_ISTRING_HASH_2(KEY) return_STRING_HASH_2 (KEY)
297
298#define ISTRING_COMPARE(X, Y, RESULT) STRING_COMPARE ((X), (Y), (RESULT))
299#define return_ISTRING_COMPARE(X, Y) return_STRING_COMPARE ((X), (Y))
300
301#endif
302
303/* hash and comparison macros for integer _key_s. */
304
305#define INTEGER_HASH_1(KEY, RESULT) do { \
306 (RESULT) += ((unsigned long)(KEY)); \
307} while (0)
308#define return_INTEGER_HASH_1(KEY) do { \
309 unsigned long _result_ = 0; \
310 INTEGER_HASH_1 ((KEY), _result_); \
311 return _result_; \
312} while (0)
313
314#define INTEGER_HASH_2(KEY, RESULT) do { \
315 (RESULT) += ~((unsigned long)(KEY)); \
316} while (0)
317#define return_INTEGER_HASH_2(KEY) do { \
318 unsigned long _result_ = 0; \
319 INTEGER_HASH_2 ((KEY), _result_); \
320 return _result_; \
321} while (0)
322
323#define INTEGER_COMPARE(X, Y, RESULT) do { \
324 (RESULT) = X - Y; \
325} while (0)
326#define return_INTEGER_COMPARE(X, Y) do { \
327 int _result_; \
328 INTEGER_COMPARE (X, Y, _result_); \
329 return _result_; \
330} while (0)
331
332/* hash and comparison macros for address keys. */
333
334#define ADDRESS_HASH_1(KEY, RESULT) INTEGER_HASH_1 (((unsigned long)(KEY)) >> 3, (RESULT))
335#define ADDRESS_HASH_2(KEY, RESULT) INTEGER_HASH_2 (((unsigned long)(KEY)) >> 3, (RESULT))
336#define ADDRESS_COMPARE(X, Y, RESULT) INTEGER_COMPARE ((X), (Y), (RESULT))
337#define return_ADDRESS_HASH_1(KEY) return_INTEGER_HASH_1 (((unsigned long)(KEY)) >> 3)
338#define return_ADDRESS_HASH_2(KEY) return_INTEGER_HASH_2 (((unsigned long)(KEY)) >> 3)
339#define return_ADDRESS_COMPARE(X, Y) return_INTEGER_COMPARE ((X), (Y))
340
341#endif /* not _hash_h_ */
Note: See TracBrowser for help on using the repository browser.