Commit | Line | Data |
8665f9e4 |
1 | /* hash.c |
a687059c |
2 | * |
4bb101f2 |
3 | * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2002, |
8665f9e4 |
4 | * 2005 by Larry Wall and others |
a687059c |
5 | * |
352d5a3a |
6 | * You may distribute under the terms of either the GNU General Public |
7 | * License or the Artistic License, as specified in the README file. |
8d063cd8 |
8 | */ |
9 | |
10 | #include <stdio.h> |
11 | #include "EXTERN.h" |
8d063cd8 |
12 | #include "a2p.h" |
9c8d0b29 |
13 | #include "util.h" |
8d063cd8 |
14 | |
011f1a1a |
15 | #ifdef NETWARE |
16 | char *savestr(char *str); |
17 | #endif |
18 | |
8d063cd8 |
19 | STR * |
f0f333f4 |
20 | hfetch(register HASH *tb, char *key) |
8d063cd8 |
21 | { |
22 | register char *s; |
23 | register int i; |
24 | register int hash; |
25 | register HENT *entry; |
26 | |
27 | if (!tb) |
2421bbdb |
28 | return NULL; |
8d063cd8 |
29 | for (s=key, i=0, hash = 0; |
30 | /* while */ *s; |
31 | s++, i++, hash *= 5) { |
32 | hash += *s * coeff[i]; |
33 | } |
34 | entry = tb->tbl_array[hash & tb->tbl_max]; |
35 | for (; entry; entry = entry->hent_next) { |
36 | if (entry->hent_hash != hash) /* strings can't be equal */ |
37 | continue; |
38 | if (strNE(entry->hent_key,key)) /* is this it? */ |
39 | continue; |
40 | return entry->hent_val; |
41 | } |
2421bbdb |
42 | return NULL; |
8d063cd8 |
43 | } |
44 | |
45 | bool |
f0f333f4 |
46 | hstore(register HASH *tb, char *key, STR *val) |
8d063cd8 |
47 | { |
48 | register char *s; |
49 | register int i; |
50 | register int hash; |
51 | register HENT *entry; |
52 | register HENT **oentry; |
53 | |
54 | if (!tb) |
55 | return FALSE; |
56 | for (s=key, i=0, hash = 0; |
57 | /* while */ *s; |
58 | s++, i++, hash *= 5) { |
59 | hash += *s * coeff[i]; |
60 | } |
61 | |
62 | oentry = &(tb->tbl_array[hash & tb->tbl_max]); |
63 | i = 1; |
64 | |
65 | for (entry = *oentry; entry; i=0, entry = entry->hent_next) { |
66 | if (entry->hent_hash != hash) /* strings can't be equal */ |
67 | continue; |
68 | if (strNE(entry->hent_key,key)) /* is this it? */ |
69 | continue; |
fe14fcc3 |
70 | /*NOSTRICT*/ |
8c52afec |
71 | safefree(entry->hent_val); |
8d063cd8 |
72 | entry->hent_val = val; |
73 | return TRUE; |
74 | } |
fe14fcc3 |
75 | /*NOSTRICT*/ |
8d063cd8 |
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 | |
9c8d0b29 |
93 | void |
f0f333f4 |
94 | hsplit(HASH *tb) |
8d063cd8 |
95 | { |
8665f9e4 |
96 | const int oldsize = tb->tbl_max + 1; |
8d063cd8 |
97 | register int newsize = oldsize * 2; |
98 | register int i; |
99 | register HENT **a; |
100 | register HENT **b; |
101 | register HENT *entry; |
102 | register HENT **oentry; |
103 | |
104 | a = (HENT**) saferealloc((char*)tb->tbl_array, newsize * sizeof(HENT*)); |
948ed65c |
105 | memset(&a[oldsize], 0, oldsize * sizeof(HENT*)); /* zero second half */ |
8d063cd8 |
106 | tb->tbl_max = --newsize; |
107 | tb->tbl_array = a; |
108 | |
109 | for (i=0; i<oldsize; i++,a++) { |
110 | if (!*a) /* non-existent */ |
111 | continue; |
112 | b = a+oldsize; |
113 | for (oentry = a, entry = *a; entry; entry = *oentry) { |
114 | if ((entry->hent_hash & newsize) != i) { |
115 | *oentry = entry->hent_next; |
116 | entry->hent_next = *b; |
117 | if (!*b) |
118 | tb->tbl_fill++; |
119 | *b = entry; |
120 | continue; |
121 | } |
122 | else |
123 | oentry = &entry->hent_next; |
124 | } |
125 | if (!*a) /* everything moved */ |
126 | tb->tbl_fill--; |
127 | } |
128 | } |
129 | |
130 | HASH * |
f0f333f4 |
131 | hnew(void) |
8d063cd8 |
132 | { |
133 | register HASH *tb = (HASH*)safemalloc(sizeof(HASH)); |
134 | |
135 | tb->tbl_array = (HENT**) safemalloc(8 * sizeof(HENT*)); |
136 | tb->tbl_fill = 0; |
137 | tb->tbl_max = 7; |
138 | hiterinit(tb); /* so each() will start off right */ |
948ed65c |
139 | memset(tb->tbl_array, 0, 8 * sizeof(HENT*)); |
8d063cd8 |
140 | return tb; |
141 | } |
142 | |
9c8d0b29 |
143 | int |
f0f333f4 |
144 | hiterinit(register HASH *tb) |
8d063cd8 |
145 | { |
146 | tb->tbl_riter = -1; |
7d879f32 |
147 | tb->tbl_eiter = (HENT*)NULL; |
8d063cd8 |
148 | return tb->tbl_fill; |
149 | } |