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
CommitLineData
463ee0b2 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
11static char rcsid[] = "$Id: pair.c,v 1.10 90/12/13 13:00:35 oz Exp $";
12#endif
13
85e6fe83 14#include "config.h"
463ee0b2 15#include "sdbm.h"
16#include "tune.h"
17#include "pair.h"
18
463ee0b2 19#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
20
21/*
22 * forward
23 */
24static 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
46int
47fitpair(pag, need)
48char *pag;
49int 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
65void
66putpair(pag, key, val)
67char *pag;
68datum key;
69datum 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
94datum
95getpair(pag, key)
96char *pag;
97datum 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
116int
117duppair(pag, key)
118char *pag;
119datum 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
126datum
127getnkey(pag, num)
128char *pag;
129int 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
147int
148delpair(pag, key)
149char *pag;
150datum 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
85e6fe83 195#ifdef HAS_MEMMOVE
a0d0e21e 196 dst -= m;
197 src -= m;
463ee0b2 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 */
221static int
222seepair(pag, n, key, siz)
223char *pag;
224register int n;
225register char *key;
226register 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
241void
242splpage(pag, new, sbit)
243char *pag;
244char *new;
245long 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 */
285int
286chkpage(pag)
287char *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}