perl 4.0.00: (no release announcement available)
[p5sagit/p5-mst-13.2.git] / x2p / hash.c
1 /* $Header: hash.c,v 4.0 91/03/20 01:57:49 lwall Locked $
2  *
3  *    Copyright (c) 1989, Larry Wall
4  *
5  *    You may distribute under the terms of the GNU General Public License
6  *    as specified in the README file that comes with the perl 3.0 kit.
7  *
8  * $Log:        hash.c,v $
9  * Revision 4.0  91/03/20  01:57:49  lwall
10  * 4.0 baseline.
11  * 
12  */
13
14 #include <stdio.h>
15 #include "EXTERN.h"
16 #include "handy.h"
17 #include "util.h"
18 #include "a2p.h"
19
20 STR *
21 hfetch(tb,key)
22 register HASH *tb;
23 char *key;
24 {
25     register char *s;
26     register int i;
27     register int hash;
28     register HENT *entry;
29
30     if (!tb)
31         return Nullstr;
32     for (s=key,         i=0,    hash = 0;
33       /* while */ *s;
34          s++,           i++,    hash *= 5) {
35         hash += *s * coeff[i];
36     }
37     entry = tb->tbl_array[hash & tb->tbl_max];
38     for (; entry; entry = entry->hent_next) {
39         if (entry->hent_hash != hash)           /* strings can't be equal */
40             continue;
41         if (strNE(entry->hent_key,key)) /* is this it? */
42             continue;
43         return entry->hent_val;
44     }
45     return Nullstr;
46 }
47
48 bool
49 hstore(tb,key,val)
50 register HASH *tb;
51 char *key;
52 STR *val;
53 {
54     register char *s;
55     register int i;
56     register int hash;
57     register HENT *entry;
58     register HENT **oentry;
59
60     if (!tb)
61         return FALSE;
62     for (s=key,         i=0,    hash = 0;
63       /* while */ *s;
64          s++,           i++,    hash *= 5) {
65         hash += *s * coeff[i];
66     }
67
68     oentry = &(tb->tbl_array[hash & tb->tbl_max]);
69     i = 1;
70
71     for (entry = *oentry; entry; i=0, entry = entry->hent_next) {
72         if (entry->hent_hash != hash)           /* strings can't be equal */
73             continue;
74         if (strNE(entry->hent_key,key)) /* is this it? */
75             continue;
76         /*NOSTRICT*/
77         safefree((char*)entry->hent_val);
78         entry->hent_val = val;
79         return TRUE;
80     }
81     /*NOSTRICT*/
82     entry = (HENT*) safemalloc(sizeof(HENT));
83
84     entry->hent_key = savestr(key);
85     entry->hent_val = val;
86     entry->hent_hash = hash;
87     entry->hent_next = *oentry;
88     *oentry = entry;
89
90     if (i) {                            /* initial entry? */
91         tb->tbl_fill++;
92         if ((tb->tbl_fill * 100 / (tb->tbl_max + 1)) > FILLPCT)
93             hsplit(tb);
94     }
95
96     return FALSE;
97 }
98
99 #ifdef NOTUSED
100 bool
101 hdelete(tb,key)
102 register HASH *tb;
103 char *key;
104 {
105     register char *s;
106     register int i;
107     register int hash;
108     register HENT *entry;
109     register HENT **oentry;
110
111     if (!tb)
112         return FALSE;
113     for (s=key,         i=0,    hash = 0;
114       /* while */ *s;
115          s++,           i++,    hash *= 5) {
116         hash += *s * coeff[i];
117     }
118
119     oentry = &(tb->tbl_array[hash & tb->tbl_max]);
120     entry = *oentry;
121     i = 1;
122     for (; entry; i=0, oentry = &entry->hent_next, entry = entry->hent_next) {
123         if (entry->hent_hash != hash)           /* strings can't be equal */
124             continue;
125         if (strNE(entry->hent_key,key)) /* is this it? */
126             continue;
127         safefree((char*)entry->hent_val);
128         safefree(entry->hent_key);
129         *oentry = entry->hent_next;
130         safefree((char*)entry);
131         if (i)
132             tb->tbl_fill--;
133         return TRUE;
134     }
135     return FALSE;
136 }
137 #endif
138
139 hsplit(tb)
140 HASH *tb;
141 {
142     int oldsize = tb->tbl_max + 1;
143     register int newsize = oldsize * 2;
144     register int i;
145     register HENT **a;
146     register HENT **b;
147     register HENT *entry;
148     register HENT **oentry;
149
150     a = (HENT**) saferealloc((char*)tb->tbl_array, newsize * sizeof(HENT*));
151     bzero((char*)&a[oldsize], oldsize * sizeof(HENT*)); /* zero second half */
152     tb->tbl_max = --newsize;
153     tb->tbl_array = a;
154
155     for (i=0; i<oldsize; i++,a++) {
156         if (!*a)                                /* non-existent */
157             continue;
158         b = a+oldsize;
159         for (oentry = a, entry = *a; entry; entry = *oentry) {
160             if ((entry->hent_hash & newsize) != i) {
161                 *oentry = entry->hent_next;
162                 entry->hent_next = *b;
163                 if (!*b)
164                     tb->tbl_fill++;
165                 *b = entry;
166                 continue;
167             }
168             else
169                 oentry = &entry->hent_next;
170         }
171         if (!*a)                                /* everything moved */
172             tb->tbl_fill--;
173     }
174 }
175
176 HASH *
177 hnew()
178 {
179     register HASH *tb = (HASH*)safemalloc(sizeof(HASH));
180
181     tb->tbl_array = (HENT**) safemalloc(8 * sizeof(HENT*));
182     tb->tbl_fill = 0;
183     tb->tbl_max = 7;
184     hiterinit(tb);      /* so each() will start off right */
185     bzero((char*)tb->tbl_array, 8 * sizeof(HENT*));
186     return tb;
187 }
188
189 #ifdef NOTUSED
190 hshow(tb)
191 register HASH *tb;
192 {
193     fprintf(stderr,"%5d %4d (%2d%%)\n",
194         tb->tbl_max+1,
195         tb->tbl_fill,
196         tb->tbl_fill * 100 / (tb->tbl_max+1));
197 }
198 #endif
199
200 hiterinit(tb)
201 register HASH *tb;
202 {
203     tb->tbl_riter = -1;
204     tb->tbl_eiter = Null(HENT*);
205     return tb->tbl_fill;
206 }
207
208 HENT *
209 hiternext(tb)
210 register HASH *tb;
211 {
212     register HENT *entry;
213
214     entry = tb->tbl_eiter;
215     do {
216         if (entry)
217             entry = entry->hent_next;
218         if (!entry) {
219             tb->tbl_riter++;
220             if (tb->tbl_riter > tb->tbl_max) {
221                 tb->tbl_riter = -1;
222                 break;
223             }
224             entry = tb->tbl_array[tb->tbl_riter];
225         }
226     } while (!entry);
227
228     tb->tbl_eiter = entry;
229     return entry;
230 }
231
232 char *
233 hiterkey(entry)
234 register HENT *entry;
235 {
236     return entry->hent_key;
237 }
238
239 STR *
240 hiterval(entry)
241 register HENT *entry;
242 {
243     return entry->hent_val;
244 }