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