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