source: trunk/minix/commands/i386/mtools-3.9.7/hash.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 4.5 KB
Line 
1/*
2 * hash.c - hash table.
3 */
4
5#include "sysincludes.h"
6#include "htable.h"
7#include "mtools.h"
8
9struct hashtable {
10 T_HashFunc f1,f2;
11 T_ComparFunc compar;
12 int size; /* actual size of the array */
13 int fill; /* number of deleted or in use slots */
14 int inuse; /* number of slots in use */
15 int max; /* maximal number of elements to keep efficient */
16 T_HashTableEl *entries;
17};
18
19static int sizes[]={5, 11, 23, 47, 97, 197, 397, 797, 1597, 3203, 6421, 12853,
20 25717, 51437, 102877, 205759, 411527, 823117, 1646237,
21 3292489, 6584983, 13169977, 26339969, 52679969, 105359939,
22 210719881, 421439783, 842879579, 1685759167, 0 };
23static int deleted=0;
24static int unallocated=0;
25
26static int alloc_ht(T_HashTable *H, int size)
27{
28 int i;
29
30 for(i=0; sizes[i]; i++)
31 if (sizes[i] > size*4 )
32 break;
33 if (!sizes[i])
34 for(i=0; sizes[i]; i++)
35 if (sizes[i] > size*2 )
36 break;
37 if (!sizes[i])
38 for(i=0; sizes[i]; i++)
39 if (sizes[i] > size)
40 break;
41 if(!sizes[i])
42 return -1;
43 size = sizes[i];
44 if(size < H->size)
45 size = H->size; /* never shrink the table */
46 H->max = size * 4 / 5 - 2;
47 H->size = size;
48 H->fill = 0;
49 H->inuse = 0;
50 H->entries = NewArray(size, T_HashTableEl);
51 if (H->entries == NULL)
52 return -1; /* out of memory error */
53
54 for(i=0; i < size; i++)
55 H->entries[i] = &unallocated;
56 return 0;
57}
58
59int make_ht(T_HashFunc f1, T_HashFunc f2, T_ComparFunc c, int size,
60 T_HashTable **H)
61{
62 *H = New(T_HashTable);
63 if (*H == NULL){
64 return -1; /* out of memory error */
65 }
66
67 (*H)->f1 = f1;
68 (*H)->f2 = f2;
69 (*H)->compar = c;
70 (*H)->size = 0;
71 if(alloc_ht(*H,size))
72 return -1;
73 return 0;
74}
75
76int free_ht(T_HashTable *H, T_HashFunc entry_free)
77{
78 int i;
79 if(entry_free)
80 for(i=0; i< H->size; i++)
81 if (H->entries[i] != &unallocated &&
82 H->entries[i] != &deleted)
83 entry_free(H->entries[i]);
84 Free(H->entries);
85 Free(H);
86 return 0;
87}
88
89/* add into hash table without checking for repeats */
90static int _hash_add(T_HashTable *H,T_HashTableEl *E, int *hint)
91{
92 int f2, pos, ctr;
93
94 pos = H->f1(E) % H->size;
95 f2 = -1;
96 ctr = 0;
97 while(H->entries[pos] != &unallocated &&
98 H->entries[pos] != &deleted){
99 if (f2 == -1)
100 f2 = H->f2(E) % (H->size - 1);
101 pos = (pos+f2+1) % H->size;
102 ctr++;
103 }
104 if(H->entries[pos] == &unallocated)
105 H->fill++; /* only increase fill if the previous element was not yet
106 * counted, i.e. unallocated */
107 H->inuse++;
108 H->entries[pos] = E;
109 if(hint)
110 *hint = pos;
111 return 0;
112}
113
114static int rehash(T_HashTable *H)
115{
116 int size,i;
117 T_HashTableEl *oldentries;
118 /* resize the table */
119
120 size = H->size;
121 oldentries = H->entries;
122 if(alloc_ht(H,((H->inuse+1)*4+H->fill)/5))
123 return -1;
124
125 for(i=0; i < size; i++){
126 if(oldentries[i] != &unallocated && oldentries[i] != &deleted)
127 _hash_add(H, oldentries[i], 0);
128 }
129 Free(oldentries);
130 return 0;
131}
132
133int hash_add(T_HashTable *H, T_HashTableEl *E, int *hint)
134{
135 if (H->fill >= H->max)
136 rehash(H);
137 if (H->fill == H->size)
138 return -1; /*out of memory error */
139 return _hash_add(H,E, hint);
140}
141
142
143/* add into hash table without checking for repeats */
144static int _hash_lookup(T_HashTable *H,T_HashTableEl *E, T_HashTableEl **E2,
145 int *hint, int isIdentity)
146{
147 int f2, pos, upos, ttl;
148
149 pos = H->f1(E) % H->size;
150 ttl = H->size;
151 f2 = -1;
152 upos = -1;
153 while(ttl &&
154 H->entries[pos] != &unallocated &&
155 (H->entries[pos] == &deleted ||
156 ((isIdentity || H->compar(H->entries[pos], E) != 0) &&
157 (!isIdentity || H->entries[pos] != E)))){
158 if (f2 == -1)
159 f2 = H->f2(E) % (H->size - 1);
160 if (upos == -1 && H->entries[pos] == &deleted)
161 upos = pos;
162 pos = (pos+f2+1) % H->size;
163 ttl--;
164 }
165 if(H->entries[pos] == &unallocated || !ttl)
166 return -1;
167 if (upos != -1){
168 H->entries[upos] = H->entries[pos];
169 H->entries[pos] = &deleted;
170 pos = upos;
171 }
172 if(hint)
173 *hint = pos;
174 *E2= H->entries[pos];
175 return 0;
176}
177
178
179int hash_lookup(T_HashTable *H,T_HashTableEl *E, T_HashTableEl **E2,
180 int *hint)
181{
182 return _hash_lookup(H, E, E2, hint, 0);
183}
184
185/* add into hash table without checking for repeats */
186int hash_remove(T_HashTable *H,T_HashTableEl *E, int hint)
187{
188 T_HashTableEl *E2;
189
190 if (hint >=0 && hint < H->size &&
191 H->entries[hint] == E){
192 H->inuse--;
193 H->entries[hint] = &deleted;
194 return 0;
195 }
196
197 if(_hash_lookup(H, E, &E2, &hint, 1)) {
198 fprintf(stderr, "Removing non-existent entry\n");
199 exit(1);
200 return -1;
201 }
202 H->inuse--;
203 H->entries[hint] = &deleted;
204 return 0;
205}
Note: See TracBrowser for help on using the repository browser.