Add cast to malloc to calm cc when system headers decalre int malloc()
[p5sagit/p5-mst-13.2.git] / ext / SDBM_File / sdbm / pair.c
1 /*
2  * sdbm - ndbm work-alike hashed database library
3  * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
4  * author: oz@nexus.yorku.ca
5  * status: public domain.
6  *
7  * page-level routines
8  */
9
10 #ifndef lint
11 static char rcsid[] = "$Id: pair.c,v 1.10 90/12/13 13:00:35 oz Exp $";
12 #endif
13
14 #include "config.h"
15 #include "sdbm.h"
16 #include "tune.h"
17 #include "pair.h"
18
19 #define exhash(item)    sdbm_hash((item).dptr, (item).dsize)
20
21 /* 
22  * forward 
23  */
24 static int seepair proto((char *, int, char *, int));
25
26 /*
27  * page format:
28  *      +------------------------------+
29  * ino  | n | keyoff | datoff | keyoff |
30  *      +------------+--------+--------+
31  *      | datoff | - - - ---->         |
32  *      +--------+---------------------+
33  *      |        F R E E A R E A       |
34  *      +--------------+---------------+
35  *      |  <---- - - - | data          |
36  *      +--------+-----+----+----------+
37  *      |  key   | data     | key      |
38  *      +--------+----------+----------+
39  *
40  * calculating the offsets for free area:  if the number
41  * of entries (ino[0]) is zero, the offset to the END of
42  * the free area is the block size. Otherwise, it is the
43  * nth (ino[ino[0]]) entry's offset.
44  */
45
46 int
47 fitpair(pag, need)
48 char *pag;
49 int need;
50 {
51         register int n;
52         register int off;
53         register int free;
54         register short *ino = (short *) pag;
55
56         off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
57         free = off - (n + 1) * sizeof(short);
58         need += 2 * sizeof(short);
59
60         debug(("free %d need %d\n", free, need));
61
62         return need <= free;
63 }
64
65 void
66 putpair(pag, key, val)
67 char *pag;
68 datum key;
69 datum val;
70 {
71         register int n;
72         register int off;
73         register short *ino = (short *) pag;
74
75         off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
76 /*
77  * enter the key first
78  */
79         off -= key.dsize;
80         (void) memcpy(pag + off, key.dptr, key.dsize);
81         ino[n + 1] = off;
82 /*
83  * now the data
84  */
85         off -= val.dsize;
86         (void) memcpy(pag + off, val.dptr, val.dsize);
87         ino[n + 2] = off;
88 /*
89  * adjust item count
90  */
91         ino[0] += 2;
92 }
93
94 datum
95 getpair(pag, key)
96 char *pag;
97 datum key;
98 {
99         register int i;
100         register int n;
101         datum val;
102         register short *ino = (short *) pag;
103
104         if ((n = ino[0]) == 0)
105                 return nullitem;
106
107         if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
108                 return nullitem;
109
110         val.dptr = pag + ino[i + 1];
111         val.dsize = ino[i] - ino[i + 1];
112         return val;
113 }
114
115 #ifdef SEEDUPS
116 int
117 duppair(pag, key)
118 char *pag;
119 datum key;
120 {
121         register short *ino = (short *) pag;
122         return ino[0] > 0 && seepair(pag, ino[0], key.dptr, key.dsize) > 0;
123 }
124 #endif
125
126 datum
127 getnkey(pag, num)
128 char *pag;
129 int num;
130 {
131         datum key;
132         register int off;
133         register short *ino = (short *) pag;
134
135         num = num * 2 - 1;
136         if (ino[0] == 0 || num > ino[0])
137                 return nullitem;
138
139         off = (num > 1) ? ino[num - 1] : PBLKSIZ;
140
141         key.dptr = pag + ino[num];
142         key.dsize = off - ino[num];
143
144         return key;
145 }
146
147 int
148 delpair(pag, key)
149 char *pag;
150 datum key;
151 {
152         register int n;
153         register int i;
154         register short *ino = (short *) pag;
155
156         if ((n = ino[0]) == 0)
157                 return 0;
158
159         if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
160                 return 0;
161 /*
162  * found the key. if it is the last entry
163  * [i.e. i == n - 1] we just adjust the entry count.
164  * hard case: move all data down onto the deleted pair,
165  * shift offsets onto deleted offsets, and adjust them.
166  * [note: 0 < i < n]
167  */
168         if (i < n - 1) {
169                 register int m;
170                 register char *dst = pag + (i == 1 ? PBLKSIZ : ino[i - 1]);
171                 register char *src = pag + ino[i + 1];
172                 register int   zoo = dst - src;
173
174                 debug(("free-up %d ", zoo));
175 /*
176  * shift data/keys down
177  */
178                 m = ino[i + 1] - ino[n];
179 #ifdef DUFF
180 #define MOVB    *--dst = *--src
181
182                 if (m > 0) {
183                         register int loop = (m + 8 - 1) >> 3;
184
185                         switch (m & (8 - 1)) {
186                         case 0: do {
187                                 MOVB;   case 7: MOVB;
188                         case 6: MOVB;   case 5: MOVB;
189                         case 4: MOVB;   case 3: MOVB;
190                         case 2: MOVB;   case 1: MOVB;
191                                 } while (--loop);
192                         }
193                 }
194 #else
195 #ifdef HAS_MEMMOVE
196                 dst -= m;
197                 src -= m;
198                 memmove(dst, src, m);
199 #else
200                 while (m--)
201                         *--dst = *--src;
202 #endif
203 #endif
204 /*
205  * adjust offset index up
206  */
207                 while (i < n - 1) {
208                         ino[i] = ino[i + 2] + zoo;
209                         i++;
210                 }
211         }
212         ino[0] -= 2;
213         return 1;
214 }
215
216 /*
217  * search for the key in the page.
218  * return offset index in the range 0 < i < n.
219  * return 0 if not found.
220  */
221 static int
222 seepair(pag, n, key, siz)
223 char *pag;
224 register int n;
225 register char *key;
226 register int siz;
227 {
228         register int i;
229         register int off = PBLKSIZ;
230         register short *ino = (short *) pag;
231
232         for (i = 1; i < n; i += 2) {
233                 if (siz == off - ino[i] &&
234                     memcmp(key, pag + ino[i], siz) == 0)
235                         return i;
236                 off = ino[i + 1];
237         }
238         return 0;
239 }
240
241 void
242 splpage(pag, new, sbit)
243 char *pag;
244 char *new;
245 long sbit;
246 {
247         datum key;
248         datum val;
249
250         register int n;
251         register int off = PBLKSIZ;
252         char cur[PBLKSIZ];
253         register short *ino = (short *) cur;
254
255         (void) memcpy(cur, pag, PBLKSIZ);
256         (void) memset(pag, 0, PBLKSIZ);
257         (void) memset(new, 0, PBLKSIZ);
258
259         n = ino[0];
260         for (ino++; n > 0; ino += 2) {
261                 key.dptr = cur + ino[0]; 
262                 key.dsize = off - ino[0];
263                 val.dptr = cur + ino[1];
264                 val.dsize = ino[0] - ino[1];
265 /*
266  * select the page pointer (by looking at sbit) and insert
267  */
268                 (void) putpair((exhash(key) & sbit) ? new : pag, key, val);
269
270                 off = ino[1];
271                 n -= 2;
272         }
273
274         debug(("%d split %d/%d\n", ((short *) cur)[0] / 2, 
275                ((short *) new)[0] / 2,
276                ((short *) pag)[0] / 2));
277 }
278
279 /*
280  * check page sanity: 
281  * number of entries should be something
282  * reasonable, and all offsets in the index should be in order.
283  * this could be made more rigorous.
284  */
285 int
286 chkpage(pag)
287 char *pag;
288 {
289         register int n;
290         register int off;
291         register short *ino = (short *) pag;
292
293         if ((n = ino[0]) < 0 || n > PBLKSIZ / sizeof(short))
294                 return 0;
295
296         if (n > 0) {
297                 off = PBLKSIZ;
298                 for (ino++; n > 0; ino += 2) {
299                         if (ino[0] > off || ino[1] > off ||
300                             ino[1] > ino[0])
301                                 return 0;
302                         off = ino[1];
303                         n -= 2;
304                 }
305         }
306         return 1;
307 }