1 /* $RCSfile: hash.c,v $$Revision: 4.0.1.3 $$Date: 92/06/08 13:26:29 $
3 * Copyright (c) 1991, Larry Wall
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
9 * Revision 4.0.1.3 92/06/08 13:26:29 lwall
10 * patch20: removed implicit int declarations on functions
11 * patch20: delete could cause %array to give too low a count of buckets filled
12 * patch20: hash tables now split only if the memory is available to do so
14 * Revision 4.0.1.2 91/11/05 17:24:13 lwall
15 * patch11: saberized perl
17 * Revision 4.0.1.1 91/06/07 11:10:11 lwall
18 * patch4: new copyright notice
20 * Revision 4.0 91/03/20 01:22:26 lwall
30 static char coeff[] = {
31 61,59,53,47,43,41,37,31,29,23,17,13,11,7,3,1,
32 61,59,53,47,43,41,37,31,29,23,17,13,11,7,3,1,
33 61,59,53,47,43,41,37,31,29,23,17,13,11,7,3,1,
34 61,59,53,47,43,41,37,31,29,23,17,13,11,7,3,1,
35 61,59,53,47,43,41,37,31,29,23,17,13,11,7,3,1,
36 61,59,53,47,43,41,37,31,29,23,17,13,11,7,3,1,
37 61,59,53,47,43,41,37,31,29,23,17,13,11,7,3,1,
38 61,59,53,47,43,41,37,31,29,23,17,13,11,7,3,1};
40 static void hfreeentries();
43 hfetch(tb,key,klen,lval)
63 Newz(503,tb->tbl_array, tb->tbl_max + 1, HENT*);
68 /* The hash function we use on symbols has to be equal to the first
69 * character when taken modulo 128, so that str_reset() can be implemented
70 * efficiently. We throw in the second character and the last character
71 * (times 128) so that long chains of identifiers starting with the
72 * same letter don't have to be strEQ'ed within hfetch(), since it
73 * compares hash values before trying strEQ().
75 if (!tb->tbl_coeffsize)
76 hash = *key + 128 * key[1] + 128 * key[klen-1]; /* assuming klen > 0 */
77 else { /* use normal coefficients */
78 if (klen < tb->tbl_coeffsize)
81 maxi = tb->tbl_coeffsize;
82 for (s=key, i=0, hash = 0;
83 i < maxi; /*SUPPRESS 8*/
84 s++, i++, hash *= 5) {
85 hash += *s * coeff[i];
89 entry = tb->tbl_array[hash & tb->tbl_max];
90 for (; entry; entry = entry->hent_next) {
91 if (entry->hent_hash != hash) /* strings can't be equal */
93 if (entry->hent_klen != klen)
95 if (bcmp(entry->hent_key,key,klen)) /* is this it? */
97 return entry->hent_val;
104 dcontent = gdbm_fetch(tb->tbl_dbm,dkey);
106 dcontent = dbm_fetch(tb->tbl_dbm,dkey);
108 if (dcontent.dptr) { /* found one */
109 str = Str_new(60,dcontent.dsize);
110 str_nset(str,dcontent.dptr,dcontent.dsize);
111 hstore(tb,key,klen,str,hash); /* cache it */
116 if (lval) { /* gonna assign to this, so it better be there */
118 hstore(tb,key,klen,str,hash);
125 hstore(tb,key,klen,val,hash)
134 register HENT *entry;
135 register HENT **oentry;
144 else if (!tb->tbl_coeffsize)
145 hash = *key + 128 * key[1] + 128 * key[klen-1];
146 else { /* use normal coefficients */
147 if (klen < tb->tbl_coeffsize)
150 maxi = tb->tbl_coeffsize;
151 for (s=key, i=0, hash = 0;
152 i < maxi; /*SUPPRESS 8*/
153 s++, i++, hash *= 5) {
154 hash += *s * coeff[i];
159 Newz(505,tb->tbl_array, tb->tbl_max + 1, HENT*);
161 oentry = &(tb->tbl_array[hash & tb->tbl_max]);
164 for (entry = *oentry; entry; i=0, entry = entry->hent_next) {
165 if (entry->hent_hash != hash) /* strings can't be equal */
167 if (entry->hent_klen != klen)
169 if (bcmp(entry->hent_key,key,klen)) /* is this it? */
171 Safefree(entry->hent_val);
172 entry->hent_val = val;
175 New(501,entry, 1, HENT);
177 entry->hent_klen = klen;
178 entry->hent_key = nsavestr(key,klen);
179 entry->hent_val = val;
180 entry->hent_hash = hash;
181 entry->hent_next = *oentry;
184 /* hdbmstore not necessary here because it's called from stabset() */
186 if (i) { /* initial entry? */
189 if (tb->tbl_dbm && tb->tbl_max >= DBM_CACHE_MAX)
192 if (tb->tbl_fill > tb->tbl_dosplit)
196 else if (tb->tbl_dbm) { /* is this just a cache for dbm file? */
197 void hentdelayfree();
199 entry = tb->tbl_array[hash & tb->tbl_max];
200 oentry = &entry->hent_next;
202 while (entry) { /* trim chain down to 1 entry */
203 *oentry = entry->hent_next;
204 hentdelayfree(entry); /* no doubt they'll want this next. */
222 register HENT *entry;
223 register HENT **oentry;
230 if (!tb || !tb->tbl_array)
232 if (!tb->tbl_coeffsize)
233 hash = *key + 128 * key[1] + 128 * key[klen-1];
234 else { /* use normal coefficients */
235 if (klen < tb->tbl_coeffsize)
238 maxi = tb->tbl_coeffsize;
239 for (s=key, i=0, hash = 0;
240 i < maxi; /*SUPPRESS 8*/
241 s++, i++, hash *= 5) {
242 hash += *s * coeff[i];
246 oentry = &(tb->tbl_array[hash & tb->tbl_max]);
249 for (; entry; i=0, oentry = &entry->hent_next, entry = *oentry) {
250 if (entry->hent_hash != hash) /* strings can't be equal */
252 if (entry->hent_klen != klen)
254 if (bcmp(entry->hent_key,key,klen)) /* is this it? */
256 *oentry = entry->hent_next;
259 str = str_mortal(entry->hent_val);
267 gdbm_delete(tb->tbl_dbm,dkey);
269 dbm_delete(tb->tbl_dbm,dkey);
287 int oldsize = tb->tbl_max + 1;
288 register int newsize = oldsize * 2;
292 register HENT *entry;
293 register HENT **oentry;
297 Renew(a, newsize, HENT*);
300 tb->tbl_dosplit = tb->tbl_max + 1; /* never split again */
303 Zero(&a[oldsize], oldsize, HENT*); /* zero 2nd half*/
304 tb->tbl_max = --newsize;
305 tb->tbl_dosplit = tb->tbl_max * FILLPCT / 100;
308 for (i=0; i<oldsize; i++,a++) {
309 if (!*a) /* non-existent */
312 for (oentry = a, entry = *a; entry; entry = *oentry) {
313 if ((entry->hent_hash & newsize) != i) {
314 *oentry = entry->hent_next;
315 entry->hent_next = *b;
322 oentry = &entry->hent_next;
324 if (!*a) /* everything moved */
335 Newz(502,tb, 1, HASH);
337 tb->tbl_coeffsize = lookat;
338 tb->tbl_max = 7; /* it's a normal associative array */
339 tb->tbl_dosplit = tb->tbl_max * FILLPCT / 100;
342 tb->tbl_max = 127; /* it's a symbol table */
343 tb->tbl_dosplit = 128; /* so never split */
349 (void)hiterinit(tb); /* so each() will start off right */
359 str_free(hent->hent_val);
360 Safefree(hent->hent_key);
370 str_2mortal(hent->hent_val); /* free between statements */
371 Safefree(hent->hent_key);
382 hfreeentries(tb,dodbm);
386 (void)memzero((char*)tb->tbl_array, (tb->tbl_max + 1) * sizeof(HENT*));
391 hfreeentries(tb,dodbm)
396 register HENT *ohent = Null(HENT*);
411 if (!tb || !tb->tbl_array)
414 if ((old_dbm = tb->tbl_dbm) && dodbm) {
416 while (dkey = gdbm_firstkey(tb->tbl_dbm), dkey.dptr) {
418 while (dkey = dbm_firstkey(tb->tbl_dbm), dkey.dptr) {
422 nextdkey = gdbm_nextkey(tb->tbl_dbm, dkey);
426 nextdkey = dbm_nextkey(tb->tbl_dbm, dkey);
428 nextdkey = dbm_nextkey(tb->tbl_dbm);
431 nextdkey = nextkey(dkey);
435 gdbm_delete(tb->tbl_dbm,dkey);
437 dbm_delete(tb->tbl_dbm,dkey);
440 } while (dkey.dptr); /* one way or another, this works */
443 tb->tbl_dbm = 0; /* now clear just cache */
447 while (hent = hiternext(tb)) { /* concise but not very efficient */
453 tb->tbl_dbm = old_dbm;
464 hfreeentries(tb,dodbm);
465 Safefree(tb->tbl_array);
474 tb->tbl_eiter = Null(HENT*);
482 register HENT *entry;
487 entry = tb->tbl_eiter;
492 key.dptr = entry->hent_key;
493 key.dsize = entry->hent_klen;
494 key = gdbm_nextkey(tb->tbl_dbm, key);
498 key.dptr = entry->hent_key;
499 key.dsize = entry->hent_klen;
500 key = dbm_nextkey(tb->tbl_dbm, key);
502 key = dbm_nextkey(tb->tbl_dbm);
505 key.dptr = entry->hent_key;
506 key.dsize = entry->hent_klen;
512 Newz(504,entry, 1, HENT);
513 tb->tbl_eiter = entry;
515 key = gdbm_firstkey(tb->tbl_dbm);
517 key = dbm_firstkey(tb->tbl_dbm);
520 entry->hent_key = key.dptr;
521 entry->hent_klen = key.dsize;
524 str_free(entry->hent_val);
526 tb->tbl_eiter = Null(HENT*);
533 Newz(506,tb->tbl_array, tb->tbl_max + 1, HENT*);
536 entry = entry->hent_next;
539 if (tb->tbl_riter > tb->tbl_max) {
543 entry = tb->tbl_array[tb->tbl_riter];
547 tb->tbl_eiter = entry;
552 hiterkey(entry,retlen)
553 register HENT *entry;
556 *retlen = entry->hent_klen;
557 return entry->hent_key;
563 register HENT *entry;
569 key.dptr = entry->hent_key;
570 key.dsize = entry->hent_klen;
572 content = gdbm_fetch(tb->tbl_dbm,key);
574 content = dbm_fetch(tb->tbl_dbm,key);
576 if (!entry->hent_val)
577 entry->hent_val = Str_new(62,0);
578 str_nset(entry->hent_val,content.dptr,content.dsize);
581 return entry->hent_val;
591 # include <sys/file.h>
602 #define O_CREAT 01000
606 static int dbmrefcnt = 0;
610 hdbmopen(tb,fname,mode)
618 if (tb->tbl_dbm) /* never really closed it */
625 hclear(tb, FALSE); /* clear cache */
628 tb->tbl_dbm = gdbm_open(fname, 0, GDBM_WRCREAT,mode, (void *) NULL);
630 tb->tbl_dbm = gdbm_open(fname, 0, GDBM_WRITER, mode, (void *) NULL);
632 tb->tbl_dbm = gdbm_open(fname, 0, GDBM_READER, mode, (void *) NULL);
636 tb->tbl_dbm = dbm_open(fname, O_RDWR|O_CREAT, mode);
638 tb->tbl_dbm = dbm_open(fname, O_RDWR, mode);
640 tb->tbl_dbm = dbm_open(fname, O_RDONLY, mode);
643 fatal("Old dbm can only open one database");
644 sprintf(buf,"%s.dir",fname);
645 if (stat(buf, &statbuf) < 0) {
646 if (mode < 0 || close(creat(buf,mode)) < 0)
648 sprintf(buf,"%s.pag",fname);
649 if (close(creat(buf,mode)) < 0)
652 tb->tbl_dbm = dbminit(fname) >= 0;
655 if (!tb->tbl_array && tb->tbl_dbm != 0)
656 Newz(507,tb->tbl_array, tb->tbl_max + 1, HENT*);
657 return tb->tbl_dbm != 0;
664 if (tb && tb->tbl_dbm) {
666 gdbm_close(tb->tbl_dbm);
670 dbm_close(tb->tbl_dbm);
673 /* dbmrefcnt--; */ /* doesn't work, rats */
678 warn("Close on unopened dbm file");
682 hdbmstore(tb,key,klen,str)
688 datum dkey, dcontent;
691 if (!tb || !tb->tbl_dbm)
695 dcontent.dptr = str_get(str);
696 dcontent.dsize = str->str_cur;
698 error = gdbm_store(tb->tbl_dbm, dkey, dcontent, GDBM_REPLACE);
700 error = dbm_store(tb->tbl_dbm, dkey, dcontent, DBM_REPLACE);
704 fatal("No write permission to dbm file");
705 warn("dbm store returned %d, errno %d, key \"%s\"",error,errno,key);
707 dbm_clearerr(tb->tbl_dbm);
712 #endif /* SOME_DBM */