1 /* Copyright (C) 1995 Free Software Foundation, Inc.
3 The GNU C Library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public License as
5 published by the Free Software Foundation; either version 2 of the
6 License, or (at your option) any later version.
8 The GNU C Library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
13 You should have received a copy of the GNU Library General Public
14 License along with the GNU C Library; see the file COPYING.LIB. If
15 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
16 Cambridge, MA 02139, USA. */
25 #define obstack_chunk_alloc xmalloc
26 #define obstack_chunk_free free
28 void *xmalloc (size_t n
);
30 typedef struct hash_entry
35 struct hash_entry
*next
;
39 /* Prototypes for local functions. */
40 static size_t lookup (hash_table
*htab
, const char *key
, size_t keylen
,
42 static unsigned long compute_hashval(const char *key
, size_t keylen
);
43 static unsigned long next_prime(unsigned long seed
);
44 static int is_prime(unsigned long candidate
);
48 init_hash(hash_table
*htab
, unsigned long init_size
)
50 /* We need the size to be a prime. */
51 init_size
= next_prime (init_size
);
53 /* Initialize the data structure. */
54 htab
->size
= init_size
;
57 htab
->table
= calloc (init_size
+ 1, sizeof (hash_entry
));
58 obstack_init (&htab
->mem_pool
);
60 return htab
->table
== NULL
;
65 delete_hash(hash_table
*htab
)
68 obstack_free (&htab
->mem_pool
, NULL
);
74 insert_entry (hash_table
*htab
, const char *key
, size_t keylen
, void *data
)
76 unsigned long hval
= compute_hashval (key
, keylen
);
77 hash_entry
*table
= (hash_entry
*) htab
->table
;
78 size_t idx
= lookup (htab
, key
, keylen
, hval
);
81 /* We don't want to overwrite the old value. */
87 /* An empty bucket has been found. */
88 table
[idx
].used
= hval
;
89 table
[idx
].key
= obstack_copy0 (&htab
->mem_pool
, key
, keylen
);
90 table
[idx
].data
= data
;
92 /* List the new value in the ordered list. */
93 for (p
= (hash_entry
**) &htab
->first
; *p
!= NULL
&& (*p
)->data
< data
;
95 if (*p
== NULL
|| (*p
)->data
> data
)
96 /* Insert new value in the list. */
103 if (100 * htab
->filled
> 90 * htab
->size
)
105 /* Resize the table. */
106 unsigned long old_size
= htab
->size
;
108 htab
->size
= next_prime (htab
->size
* 2);
111 htab
->table
= calloc (htab
->size
, sizeof (hash_entry
));
113 for (idx
= 1; idx
<= old_size
; ++idx
)
115 insert_entry (htab
, table
[idx
].key
, strlen(table
[idx
].key
),
127 find_entry (hash_table
*htab
, const char *key
, size_t keylen
, void **result
)
129 hash_entry
*table
= (hash_entry
*) htab
->table
;
130 size_t idx
= lookup (htab
, key
, keylen
, compute_hashval (key
, keylen
));
133 retval
= table
[idx
].used
;
134 *result
= retval
? table
[idx
].data
: NULL
;
141 iterate_table (hash_table
*htab
, void **ptr
, void **result
)
144 *ptr
= (void *) htab
->first
;
147 *ptr
= (void *) (((hash_entry
*) *ptr
)->next
);
152 *result
= ((hash_entry
*) *ptr
)->data
;
158 lookup (hash_table
*htab
, const char *key
, size_t keylen
, unsigned long hval
)
162 hash_entry
*table
= (hash_entry
*) htab
->table
;
164 /* First hash function: simply take the modul but prevent zero. */
165 hash
= 1 + hval
% htab
->size
;
171 if (table
[idx
].used
== hval
&& table
[idx
].key
[keylen
] == '\0'
172 && strncmp (key
, table
[idx
].key
, keylen
) == 0)
175 /* Second hash function as suggested in [Knuth]. */
176 hash
= 1 + hash
% (htab
->size
- 2);
181 idx
= htab
->size
+ idx
- hash
;
185 /* If entry is found use it. */
186 if (table
[idx
].used
== hval
&& table
[idx
].key
[keylen
] == '\0'
187 && strncmp (key
, table
[idx
].key
, keylen
) == 0)
190 while (table
[idx
].used
);
197 compute_hashval(const char *key
, size_t keylen
)
200 unsigned long hval
, g
;
201 /* Compute the hash value for the given string. */
208 g
= hval
& (0xf << (LONGBITS
- 4));
211 hval
^= g
>> (LONGBITS
- 8);
220 next_prime(unsigned long seed
)
222 /* Make it definitely odd. */
225 while (!is_prime (seed
))
233 is_prime(unsigned long candidate
)
235 /* No even number and none less than 10 will be passwd here. */
236 unsigned long div
= 3;
237 unsigned long sq
= div
* div
;
239 while (sq
< candidate
&& candidate
% div
!= 0)
246 return candidate
% div
!= 0;