Fix excessive calls to random_byte()
[u/mdw/putty] / tree234.c
CommitLineData
febd9a0f 1/*
2 * tree234.c: reasonably generic 2-3-4 tree routines. Currently
3 * supports insert, delete, find and iterate operations.
4 */
5
6#include <stdio.h>
7#include <stdlib.h>
8
dcbde236 9#include "puttymem.h"
10
febd9a0f 11#include "tree234.h"
12
dcbde236 13#define mknew(typ) ( (typ *) smalloc (sizeof (typ)) )
14/* #define sfree free */
febd9a0f 15
16#ifdef TEST
17#define LOG(x) (printf x)
18#else
19#define LOG(x)
20#endif
21
22struct tree234_Tag {
23 node234 *root;
24 cmpfn234 cmp;
25};
26
27struct node234_Tag {
28 node234 *parent;
29 node234 *kids[4];
30 void *elems[3];
31};
32
33/*
34 * Create a 2-3-4 tree.
35 */
36tree234 *newtree234(cmpfn234 cmp) {
37 tree234 *ret = mknew(tree234);
38 LOG(("created tree %p\n", ret));
39 ret->root = NULL;
40 ret->cmp = cmp;
41 return ret;
42}
43
44/*
45 * Free a 2-3-4 tree (not including freeing the elements).
46 */
47static void freenode234(node234 *n) {
48 if (!n)
49 return;
50 freenode234(n->kids[0]);
51 freenode234(n->kids[1]);
52 freenode234(n->kids[2]);
53 freenode234(n->kids[3]);
54 sfree(n);
55}
56void freetree234(tree234 *t) {
57 freenode234(t->root);
58 sfree(t);
59}
60
61/*
62 * Add an element e to a 2-3-4 tree t. Returns e on success, or if
63 * an existing element compares equal, returns that.
64 */
65void *add234(tree234 *t, void *e) {
66 node234 *n, **np, *left, *right;
67 void *orig_e = e;
68 int c;
69
70 LOG(("adding node %p to tree %p\n", e, t));
71 if (t->root == NULL) {
72 t->root = mknew(node234);
73 t->root->elems[1] = t->root->elems[2] = NULL;
74 t->root->kids[0] = t->root->kids[1] = NULL;
75 t->root->kids[2] = t->root->kids[3] = NULL;
76 t->root->parent = NULL;
77 t->root->elems[0] = e;
78 LOG((" created root %p\n", t->root));
79 return orig_e;
80 }
81
82 np = &t->root;
83 while (*np) {
84 n = *np;
85 LOG((" node %p: %p [%p] %p [%p] %p [%p] %p\n",
86 n, n->kids[0], n->elems[0], n->kids[1], n->elems[1],
87 n->kids[2], n->elems[2], n->kids[3]));
88 if ((c = t->cmp(e, n->elems[0])) < 0)
89 np = &n->kids[0];
90 else if (c == 0)
91 return n->elems[0]; /* already exists */
92 else if (n->elems[1] == NULL || (c = t->cmp(e, n->elems[1])) < 0)
93 np = &n->kids[1];
94 else if (c == 0)
95 return n->elems[1]; /* already exists */
96 else if (n->elems[2] == NULL || (c = t->cmp(e, n->elems[2])) < 0)
97 np = &n->kids[2];
98 else if (c == 0)
99 return n->elems[2]; /* already exists */
100 else
101 np = &n->kids[3];
102 LOG((" moving to child %d (%p)\n", np - n->kids, *np));
103 }
104
105 /*
106 * We need to insert the new element in n at position np.
107 */
108 left = NULL;
109 right = NULL;
110 while (n) {
111 LOG((" at %p: %p [%p] %p [%p] %p [%p] %p\n",
112 n, n->kids[0], n->elems[0], n->kids[1], n->elems[1],
113 n->kids[2], n->elems[2], n->kids[3]));
114 LOG((" need to insert %p [%p] %p at position %d\n",
115 left, e, right, np - n->kids));
116 if (n->elems[1] == NULL) {
117 /*
118 * Insert in a 2-node; simple.
119 */
120 if (np == &n->kids[0]) {
121 LOG((" inserting on left of 2-node\n"));
122 n->kids[2] = n->kids[1];
123 n->elems[1] = n->elems[0];
124 n->kids[1] = right;
125 n->elems[0] = e;
126 n->kids[0] = left;
127 } else { /* np == &n->kids[1] */
128 LOG((" inserting on right of 2-node\n"));
129 n->kids[2] = right;
130 n->elems[1] = e;
131 n->kids[1] = left;
132 }
133 if (n->kids[0]) n->kids[0]->parent = n;
134 if (n->kids[1]) n->kids[1]->parent = n;
135 if (n->kids[2]) n->kids[2]->parent = n;
136 LOG((" done\n"));
137 break;
138 } else if (n->elems[2] == NULL) {
139 /*
140 * Insert in a 3-node; simple.
141 */
142 if (np == &n->kids[0]) {
143 LOG((" inserting on left of 3-node\n"));
144 n->kids[3] = n->kids[2];
145 n->elems[2] = n->elems[1];
146 n->kids[2] = n->kids[1];
147 n->elems[1] = n->elems[0];
148 n->kids[1] = right;
149 n->elems[0] = e;
150 n->kids[0] = left;
151 } else if (np == &n->kids[1]) {
152 LOG((" inserting in middle of 3-node\n"));
153 n->kids[3] = n->kids[2];
154 n->elems[2] = n->elems[1];
155 n->kids[2] = right;
156 n->elems[1] = e;
157 n->kids[1] = left;
158 } else { /* np == &n->kids[2] */
159 LOG((" inserting on right of 3-node\n"));
160 n->kids[3] = right;
161 n->elems[2] = e;
162 n->kids[2] = left;
163 }
164 if (n->kids[0]) n->kids[0]->parent = n;
165 if (n->kids[1]) n->kids[1]->parent = n;
166 if (n->kids[2]) n->kids[2]->parent = n;
167 if (n->kids[3]) n->kids[3]->parent = n;
168 LOG((" done\n"));
169 break;
170 } else {
171 node234 *m = mknew(node234);
172 m->parent = n->parent;
173 LOG((" splitting a 4-node; created new node %p\n", m));
174 /*
175 * Insert in a 4-node; split into a 2-node and a
176 * 3-node, and move focus up a level.
177 *
178 * I don't think it matters which way round we put the
179 * 2 and the 3. For simplicity, we'll put the 3 first
180 * always.
181 */
182 if (np == &n->kids[0]) {
183 m->kids[0] = left;
184 m->elems[0] = e;
185 m->kids[1] = right;
186 m->elems[1] = n->elems[0];
187 m->kids[2] = n->kids[1];
188 e = n->elems[1];
189 n->kids[0] = n->kids[2];
190 n->elems[0] = n->elems[2];
191 n->kids[1] = n->kids[3];
192 } else if (np == &n->kids[1]) {
193 m->kids[0] = n->kids[0];
194 m->elems[0] = n->elems[0];
195 m->kids[1] = left;
196 m->elems[1] = e;
197 m->kids[2] = right;
198 e = n->elems[1];
199 n->kids[0] = n->kids[2];
200 n->elems[0] = n->elems[2];
201 n->kids[1] = n->kids[3];
202 } else if (np == &n->kids[2]) {
203 m->kids[0] = n->kids[0];
204 m->elems[0] = n->elems[0];
205 m->kids[1] = n->kids[1];
206 m->elems[1] = n->elems[1];
207 m->kids[2] = left;
208 /* e = e; */
209 n->kids[0] = right;
210 n->elems[0] = n->elems[2];
211 n->kids[1] = n->kids[3];
212 } else { /* np == &n->kids[3] */
213 m->kids[0] = n->kids[0];
214 m->elems[0] = n->elems[0];
215 m->kids[1] = n->kids[1];
216 m->elems[1] = n->elems[1];
217 m->kids[2] = n->kids[2];
218 n->kids[0] = left;
219 n->elems[0] = e;
220 n->kids[1] = right;
221 e = n->elems[2];
222 }
223 m->kids[3] = n->kids[3] = n->kids[2] = NULL;
224 m->elems[2] = n->elems[2] = n->elems[1] = NULL;
225 if (m->kids[0]) m->kids[0]->parent = m;
226 if (m->kids[1]) m->kids[1]->parent = m;
227 if (m->kids[2]) m->kids[2]->parent = m;
228 if (n->kids[0]) n->kids[0]->parent = n;
229 if (n->kids[1]) n->kids[1]->parent = n;
230 LOG((" left (%p): %p [%p] %p [%p] %p\n", m,
231 m->kids[0], m->elems[0],
232 m->kids[1], m->elems[1],
233 m->kids[2]));
234 LOG((" right (%p): %p [%p] %p\n", n,
235 n->kids[0], n->elems[0],
236 n->kids[1]));
237 left = m;
238 right = n;
239 }
240 if (n->parent)
241 np = (n->parent->kids[0] == n ? &n->parent->kids[0] :
242 n->parent->kids[1] == n ? &n->parent->kids[1] :
243 n->parent->kids[2] == n ? &n->parent->kids[2] :
244 &n->parent->kids[3]);
245 n = n->parent;
246 }
247
248 /*
249 * If we've come out of here by `break', n will still be
250 * non-NULL and we've finished. If we've come here because n is
251 * NULL, we need to create a new root for the tree because the
252 * old one has just split into two.
253 */
254 if (!n) {
255 LOG((" root is overloaded, split into two\n"));
256 t->root = mknew(node234);
257 t->root->kids[0] = left;
258 t->root->elems[0] = e;
259 t->root->kids[1] = right;
260 t->root->elems[1] = NULL;
261 t->root->kids[2] = NULL;
262 t->root->elems[2] = NULL;
263 t->root->kids[3] = NULL;
264 t->root->parent = NULL;
265 if (t->root->kids[0]) t->root->kids[0]->parent = t->root;
266 if (t->root->kids[1]) t->root->kids[1]->parent = t->root;
267 LOG((" new root is %p [%p] %p\n",
268 t->root->kids[0], t->root->elems[0], t->root->kids[1]));
269 }
270
271 return orig_e;
272}
273
274/*
275 * Find an element e in a 2-3-4 tree t. Returns NULL if not found.
276 * e is always passed as the first argument to cmp, so cmp can be
277 * an asymmetric function if desired. cmp can also be passed as
278 * NULL, in which case the compare function from the tree proper
279 * will be used.
280 */
281void *find234(tree234 *t, void *e, cmpfn234 cmp) {
282 node234 *n;
283 int c;
284
285 if (t->root == NULL)
286 return NULL;
287
288 if (cmp == NULL)
289 cmp = t->cmp;
290
291 n = t->root;
292 while (n) {
81d77872 293 if ( (c = cmp(e, n->elems[0])) < 0)
febd9a0f 294 n = n->kids[0];
295 else if (c == 0)
296 return n->elems[0];
81d77872 297 else if (n->elems[1] == NULL || (c = cmp(e, n->elems[1])) < 0)
febd9a0f 298 n = n->kids[1];
299 else if (c == 0)
300 return n->elems[1];
81d77872 301 else if (n->elems[2] == NULL || (c = cmp(e, n->elems[2])) < 0)
febd9a0f 302 n = n->kids[2];
303 else if (c == 0)
304 return n->elems[2];
305 else
306 n = n->kids[3];
307 }
308
309 /*
310 * We've found our way to the bottom of the tree and we know
311 * where we would insert this node if we wanted to. But it
312 * isn't there.
313 */
314 return NULL;
315}
316
317/*
318 * Delete an element e in a 2-3-4 tree. Does not free the element,
319 * merely removes all links to it from the tree nodes.
320 */
81d77872 321void del234(tree234 *t, void *e) {
febd9a0f 322 node234 *n;
323 int ei = -1;
324
325 n = t->root;
326 LOG(("deleting %p from tree %p\n", e, t));
327 while (1) {
328 while (n) {
329 int c;
330 int ki;
331 node234 *sub;
332
333 LOG((" node %p: %p [%p] %p [%p] %p [%p] %p\n",
334 n, n->kids[0], n->elems[0], n->kids[1], n->elems[1],
335 n->kids[2], n->elems[2], n->kids[3]));
336 if ((c = t->cmp(e, n->elems[0])) < 0) {
337 ki = 0;
338 } else if (c == 0) {
339 ei = 0; break;
340 } else if (n->elems[1] == NULL || (c = t->cmp(e, n->elems[1])) < 0) {
341 ki = 1;
342 } else if (c == 0) {
343 ei = 1; break;
344 } else if (n->elems[2] == NULL || (c = t->cmp(e, n->elems[2])) < 0) {
345 ki = 2;
346 } else if (c == 0) {
347 ei = 2; break;
348 } else {
349 ki = 3;
350 }
351 /*
352 * Recurse down to subtree ki. If it has only one element,
353 * we have to do some transformation to start with.
354 */
355 LOG((" moving to subtree %d\n", ki));
356 sub = n->kids[ki];
357 if (!sub->elems[1]) {
358 LOG((" subtree has only one element!\n", ki));
359 if (ki > 0 && n->kids[ki-1]->elems[1]) {
360 /*
361 * Case 3a, left-handed variant. Child ki has
362 * only one element, but child ki-1 has two or
363 * more. So we need to move a subtree from ki-1
364 * to ki.
365 *
366 * . C . . B .
367 * / \ -> / \
368 * [more] a A b B c d D e [more] a A b c C d D e
369 */
370 node234 *sib = n->kids[ki-1];
371 int lastelem = (sib->elems[2] ? 2 :
372 sib->elems[1] ? 1 : 0);
373 sub->kids[2] = sub->kids[1];
374 sub->elems[1] = sub->elems[0];
375 sub->kids[1] = sub->kids[0];
376 sub->elems[0] = n->elems[ki-1];
377 sub->kids[0] = sib->kids[lastelem+1];
100122a9 378 if (sub->kids[0]) sub->kids[0]->parent = sub;
febd9a0f 379 n->elems[ki-1] = sib->elems[lastelem];
380 sib->kids[lastelem+1] = NULL;
381 sib->elems[lastelem] = NULL;
382 LOG((" case 3a left\n"));
383 } else if (ki < 3 && n->kids[ki+1] &&
384 n->kids[ki+1]->elems[1]) {
385 /*
386 * Case 3a, right-handed variant. ki has only
387 * one element but ki+1 has two or more. Move a
388 * subtree from ki+1 to ki.
389 *
390 * . B . . C .
391 * / \ -> / \
392 * a A b c C d D e [more] a A b B c d D e [more]
393 */
394 node234 *sib = n->kids[ki+1];
395 int j;
396 sub->elems[1] = n->elems[ki];
397 sub->kids[2] = sib->kids[0];
100122a9 398 if (sub->kids[2]) sub->kids[2]->parent = sub;
febd9a0f 399 n->elems[ki] = sib->elems[0];
400 sib->kids[0] = sib->kids[1];
401 for (j = 0; j < 2 && sib->elems[j+1]; j++) {
402 sib->kids[j+1] = sib->kids[j+2];
403 sib->elems[j] = sib->elems[j+1];
404 }
405 sib->kids[j+1] = NULL;
406 sib->elems[j] = NULL;
407 LOG((" case 3a right\n"));
408 } else {
409 /*
410 * Case 3b. ki has only one element, and has no
411 * neighbour with more than one. So pick a
412 * neighbour and merge it with ki, taking an
413 * element down from n to go in the middle.
414 *
415 * . B . .
416 * / \ -> |
417 * a A b c C d a A b B c C d
418 *
419 * (Since at all points we have avoided
420 * descending to a node with only one element,
421 * we can be sure that n is not reduced to
422 * nothingness by this move, _unless_ it was
423 * the very first node, ie the root of the
424 * tree. In that case we remove the now-empty
425 * root and replace it with its single large
426 * child as shown.)
427 */
428 node234 *sib;
429 int j;
430
431 if (ki > 0)
432 ki--;
433 sib = n->kids[ki];
434 sub = n->kids[ki+1];
435
436 sub->kids[3] = sub->kids[1];
437 sub->elems[2] = sub->elems[0];
438 sub->kids[2] = sub->kids[0];
439 sub->elems[1] = n->elems[ki];
440 sub->kids[1] = sib->kids[1];
100122a9 441 if (sub->kids[1]) sub->kids[1]->parent = sub;
febd9a0f 442 sub->elems[0] = sib->elems[0];
443 sub->kids[0] = sib->kids[0];
100122a9 444 if (sub->kids[0]) sub->kids[0]->parent = sub;
febd9a0f 445
446 sfree(sib);
447
448 /*
449 * That's built the big node in sub. Now we
450 * need to remove the reference to sib in n.
451 */
452 for (j = ki; j < 3 && n->kids[j+1]; j++) {
453 n->kids[j] = n->kids[j+1];
454 n->elems[j] = j<2 ? n->elems[j+1] : NULL;
455 }
456 n->kids[j] = NULL;
457 if (j < 3) n->elems[j] = NULL;
2d56b16f 458 LOG((" case 3b ki=%d\n", ki));
febd9a0f 459
460 if (!n->elems[0]) {
461 /*
462 * The root is empty and needs to be
463 * removed.
464 */
465 LOG((" shifting root!\n"));
466 t->root = sub;
467 sub->parent = NULL;
468 sfree(n);
469 }
470 }
471 }
472 n = sub;
473 }
474 if (ei==-1)
475 return; /* nothing to do; `already removed' */
476
477 /*
478 * Treat special case: this is the one remaining item in
479 * the tree. n is the tree root (no parent), has one
480 * element (no elems[1]), and has no kids (no kids[0]).
481 */
482 if (!n->parent && !n->elems[1] && !n->kids[0]) {
483 LOG((" removed last element in tree\n"));
484 sfree(n);
485 t->root = NULL;
486 return;
487 }
488
489 /*
490 * Now we have the element we want, as n->elems[ei], and we
491 * have also arranged for that element not to be the only
492 * one in its node. So...
493 */
494
495 if (!n->kids[0] && n->elems[1]) {
496 /*
497 * Case 1. n is a leaf node with more than one element,
498 * so it's _really easy_. Just delete the thing and
499 * we're done.
500 */
501 int i;
502 LOG((" case 1\n"));
a4a19e73 503 for (i = ei; i < 2 && n->elems[i+1]; i++)
febd9a0f 504 n->elems[i] = n->elems[i+1];
505 n->elems[i] = NULL;
506 return; /* finished! */
507 } else if (n->kids[ei]->elems[1]) {
508 /*
509 * Case 2a. n is an internal node, and the root of the
510 * subtree to the left of e has more than one element.
511 * So find the predecessor p to e (ie the largest node
512 * in that subtree), place it where e currently is, and
513 * then start the deletion process over again on the
514 * subtree with p as target.
515 */
516 node234 *m = n->kids[ei];
517 void *target;
518 LOG((" case 2a\n"));
519 while (m->kids[0]) {
520 m = (m->kids[3] ? m->kids[3] :
521 m->kids[2] ? m->kids[2] :
522 m->kids[1] ? m->kids[1] : m->kids[0]);
523 }
524 target = (m->elems[2] ? m->elems[2] :
525 m->elems[1] ? m->elems[1] : m->elems[0]);
526 n->elems[ei] = target;
527 n = n->kids[ei];
528 e = target;
529 } else if (n->kids[ei+1]->elems[1]) {
530 /*
531 * Case 2b, symmetric to 2a but s/left/right/ and
532 * s/predecessor/successor/. (And s/largest/smallest/).
533 */
534 node234 *m = n->kids[ei+1];
535 void *target;
536 LOG((" case 2b\n"));
537 while (m->kids[0]) {
538 m = m->kids[0];
539 }
540 target = m->elems[0];
541 n->elems[ei] = target;
542 n = n->kids[ei+1];
543 e = target;
544 } else {
545 /*
546 * Case 2c. n is an internal node, and the subtrees to
547 * the left and right of e both have only one element.
548 * So combine the two subnodes into a single big node
549 * with their own elements on the left and right and e
550 * in the middle, then restart the deletion process on
551 * that subtree, with e still as target.
552 */
553 node234 *a = n->kids[ei], *b = n->kids[ei+1];
554 int j;
555
556 LOG((" case 2c\n"));
557 a->elems[1] = n->elems[ei];
558 a->kids[2] = b->kids[0];
100122a9 559 if (a->kids[2]) a->kids[2]->parent = a;
febd9a0f 560 a->elems[2] = b->elems[0];
561 a->kids[3] = b->kids[1];
100122a9 562 if (a->kids[3]) a->kids[3]->parent = a;
febd9a0f 563 sfree(b);
564 /*
565 * That's built the big node in a, and destroyed b. Now
566 * remove the reference to b (and e) in n.
567 */
568 for (j = ei; j < 2 && n->elems[j+1]; j++) {
569 n->elems[j] = n->elems[j+1];
570 n->kids[j+1] = n->kids[j+2];
571 }
572 n->elems[j] = NULL;
573 n->kids[j+1] = NULL;
e9e9556d 574 /*
575 * It's possible, in this case, that we've just removed
576 * the only element in the root of the tree. If so,
577 * shift the root.
578 */
579 if (n->elems[0] == NULL) {
580 LOG((" shifting root!\n"));
581 t->root = a;
582 a->parent = NULL;
583 sfree(n);
584 }
febd9a0f 585 /*
586 * Now go round the deletion process again, with n
587 * pointing at the new big node and e still the same.
588 */
589 n = a;
590 }
591 }
592}
593
594/*
595 * Iterate over the elements of a tree234, in order.
596 */
597void *first234(tree234 *t, enum234 *e) {
598 node234 *n = t->root;
599 if (!n)
600 return NULL;
601 while (n->kids[0])
602 n = n->kids[0];
603 e->node = n;
604 e->posn = 0;
605 return n->elems[0];
606}
607
608void *next234(enum234 *e) {
609 node234 *n = e->node;
610 int pos = e->posn;
611
612 if (n->kids[pos+1]) {
613 n = n->kids[pos+1];
614 while (n->kids[0])
615 n = n->kids[0];
616 e->node = n;
617 e->posn = 0;
618 return n->elems[0];
619 }
620
6aff1005 621 if (pos < 2 && n->elems[pos+1]) {
622 e->posn = pos+1;
623 return n->elems[e->posn];
febd9a0f 624 }
625
626 do {
627 node234 *nn = n->parent;
628 if (nn == NULL)
629 return NULL; /* end of tree */
630 pos = (nn->kids[0] == n ? 0 :
631 nn->kids[1] == n ? 1 :
632 nn->kids[2] == n ? 2 : 3);
633 n = nn;
634 } while (pos == 3 || n->kids[pos+1] == NULL);
635
636 e->node = n;
637 e->posn = pos;
638 return n->elems[pos];
639}
640
641#ifdef TEST
642
2d56b16f 643/*
644 * Test code for the 2-3-4 tree. This code maintains an alternative
645 * representation of the data in the tree, in an array (using the
646 * obvious and slow insert and delete functions). After each tree
7aa7c43a 647 * operation, the verify() function is called, which ensures all
648 * the tree properties are preserved (node->child->parent always
649 * equals node; number of kids == 0 or number of elements + 1;
650 * ordering property between elements of a node and elements of its
651 * children is preserved; tree has the same depth everywhere; every
652 * node has at least one element) and also ensures the list
653 * represented by the tree is the same list it should be. (This
654 * last check also verifies the ordering properties, because the
655 * `same list it should be' is by definition correctly ordered. It
656 * also ensures all nodes are distinct, because the enum functions
657 * would get caught in a loop if not.)
2d56b16f 658 */
659
660#include <stdarg.h>
661
662/*
663 * Error reporting function.
664 */
665void error(char *fmt, ...) {
666 va_list ap;
667 printf("ERROR: ");
668 va_start(ap, fmt);
669 vfprintf(stdout, fmt, ap);
670 va_end(ap);
671 printf("\n");
672}
673
674/* The array representation of the data. */
675void **array;
676int arraylen, arraysize;
677cmpfn234 cmp;
678
679/* The tree representation of the same data. */
680tree234 *tree;
681
682typedef struct {
683 int treedepth;
684 int elemcount;
685} chkctx;
686
687void chknode(chkctx *ctx, int level, node234 *node,
688 void *lowbound, void *highbound) {
689 int nkids, nelems;
690 int i;
691
692 /* Count the non-NULL kids. */
693 for (nkids = 0; nkids < 4 && node->kids[nkids]; nkids++);
694 /* Ensure no kids beyond the first NULL are non-NULL. */
695 for (i = nkids; i < 4; i++)
696 if (node->kids[i]) {
697 error("node %p: nkids=%d but kids[%d] non-NULL",
698 node, nkids, i);
699 }
700
701 /* Count the non-NULL elements. */
702 for (nelems = 0; nelems < 3 && node->elems[nelems]; nelems++);
703 /* Ensure no elements beyond the first NULL are non-NULL. */
704 for (i = nelems; i < 3; i++)
705 if (node->elems[i]) {
706 error("node %p: nelems=%d but elems[%d] non-NULL",
707 node, nelems, i);
708 }
709
710 if (nkids == 0) {
711 /*
712 * If nkids==0, this is a leaf node; verify that the tree
713 * depth is the same everywhere.
714 */
715 if (ctx->treedepth < 0)
716 ctx->treedepth = level; /* we didn't know the depth yet */
717 else if (ctx->treedepth != level)
718 error("node %p: leaf at depth %d, previously seen depth %d",
719 node, level, ctx->treedepth);
720 } else {
721 /*
722 * If nkids != 0, then it should be nelems+1, unless nelems
723 * is 0 in which case nkids should also be 0 (and so we
724 * shouldn't be in this condition at all).
725 */
726 int shouldkids = (nelems ? nelems+1 : 0);
727 if (nkids != shouldkids) {
728 error("node %p: %d elems should mean %d kids but has %d",
729 node, nelems, shouldkids, nkids);
730 }
731 }
732
733 /*
734 * nelems should be at least 1.
735 */
736 if (nelems == 0) {
737 error("node %p: no elems", node, nkids);
738 }
739
740 /*
741 * Add nelems to the running element count of the whole tree
742 * (to ensure the enum234 routines see them all).
743 */
744 ctx->elemcount += nelems;
745
746 /*
747 * Check ordering property: all elements should be strictly >
748 * lowbound, strictly < highbound, and strictly < each other in
749 * sequence. (lowbound and highbound are NULL at edges of tree
750 * - both NULL at root node - and NULL is considered to be <
751 * everything and > everything. IYSWIM.)
752 */
753 for (i = -1; i < nelems; i++) {
754 void *lower = (i == -1 ? lowbound : node->elems[i]);
755 void *higher = (i+1 == nelems ? highbound : node->elems[i+1]);
756 if (lower && higher && cmp(lower, higher) >= 0) {
757 error("node %p: kid comparison [%d=%s,%d=%s] failed",
758 node, i, lower, i+1, higher);
759 }
760 }
761
762 /*
763 * Check parent pointers: all non-NULL kids should have a
764 * parent pointer coming back to this node.
765 */
766 for (i = 0; i < nkids; i++)
767 if (node->kids[i]->parent != node) {
768 error("node %p kid %d: parent ptr is %p not %p",
769 node, i, node->kids[i]->parent, node);
770 }
771
772
773 /*
774 * Now (finally!) recurse into subtrees.
775 */
776 for (i = 0; i < nkids; i++) {
777 void *lower = (i == 0 ? lowbound : node->elems[i-1]);
778 void *higher = (i >= nelems ? highbound : node->elems[i]);
779 chknode(ctx, level+1, node->kids[i], lower, higher);
780 }
781}
782
783void verify(void) {
784 chkctx ctx;
785 enum234 e;
786 int i;
787 void *p;
788
789 ctx.treedepth = -1; /* depth unknown yet */
790 ctx.elemcount = 0; /* no elements seen yet */
791 /*
792 * Verify validity of tree properties.
793 */
794 if (tree->root)
795 chknode(&ctx, 0, tree->root, NULL, NULL);
796 printf("tree depth: %d\n", ctx.treedepth);
797 /*
798 * Enumerate the tree and ensure it matches up to the array.
799 */
800 for (i = 0, p = first234(tree, &e);
801 p;
802 i++, p = next234(&e)) {
803 if (i >= arraylen)
804 error("tree contains more than %d elements", arraylen);
805 if (array[i] != p)
806 error("enum at position %d: array says %s, tree says %s",
807 i, array[i], p);
808 }
809 if (i != ctx.elemcount) {
810 error("tree really contains %d elements, enum gave %d",
811 i, ctx.elemcount);
812 }
813 if (i < arraylen) {
814 error("enum gave only %d elements, array has %d", i, arraylen);
815 }
816}
817
818void addtest(void *elem) {
819 int i, j;
820 void *retval, *realret;
821
822 if (arraysize < arraylen+1) {
823 arraysize = arraylen+1+256;
dcbde236 824 array = (array == NULL ? smalloc(arraysize*sizeof(*array)) :
825 srealloc(array, arraysize*sizeof(*array)));
2d56b16f 826 }
827
828 i = 0;
829 while (i < arraylen && cmp(elem, array[i]) > 0)
830 i++;
831 /* now i points to the first element >= elem */
832 if (i < arraylen && !cmp(elem, array[i]))
833 retval = array[i]; /* expect that returned not elem */
834 else {
835 retval = elem; /* expect elem returned (success) */
836 for (j = arraylen; j > i; j--)
837 array[j] = array[j-1];
838 array[i] = elem; /* add elem to array */
839 arraylen++;
840 }
841
842 realret = add234(tree, elem);
843 if (realret != retval) {
844 error("add: retval was %p expected %p", realret, retval);
845 }
846
847 verify();
848}
849
850void deltest(void *elem) {
851 int i;
852
853 i = 0;
854 while (i < arraylen && cmp(elem, array[i]) > 0)
855 i++;
856 /* now i points to the first element >= elem */
857 if (i >= arraylen || cmp(elem, array[i]) != 0)
858 return; /* don't do it! */
859 else {
860 while (i < arraylen-1) {
861 array[i] = array[i+1];
862 i++;
863 }
864 arraylen--; /* delete elem from array */
865 }
866
867 del234(tree, elem);
868
869 verify();
febd9a0f 870}
2d56b16f 871
872/* A sample data set and test utility. Designed for pseudo-randomness,
873 * and yet repeatability. */
874
875/*
876 * This random number generator uses the `portable implementation'
877 * given in ANSI C99 draft N869. It assumes `unsigned' is 32 bits;
878 * change it if not.
879 */
880int randomnumber(unsigned *seed) {
881 *seed *= 1103515245;
882 *seed += 12345;
883 return ((*seed) / 65536) % 32768;
febd9a0f 884}
885
2d56b16f 886int mycmp(void *av, void *bv) {
887 char const *a = (char const *)av;
888 char const *b = (char const *)bv;
febd9a0f 889 return strcmp(a, b);
890}
891
2d56b16f 892#define lenof(x) ( sizeof((x)) / sizeof(*(x)) )
893
894char *strings[] = {
895 "a", "ab", "absque", "coram", "de",
896 "palam", "clam", "cum", "ex", "e",
897 "sine", "tenus", "pro", "prae",
898 "banana", "carrot", "cabbage", "broccoli", "onion", "zebra",
899 "penguin", "blancmange", "pangolin", "whale", "hedgehog",
900 "giraffe", "peanut", "bungee", "foo", "bar", "baz", "quux",
901 "murfl", "spoo", "breen", "flarn", "octothorpe",
902 "snail", "tiger", "elephant", "octopus", "warthog", "armadillo",
903 "aardvark", "wyvern", "dragon", "elf", "dwarf", "orc", "goblin",
904 "pixie", "basilisk", "warg", "ape", "lizard", "newt", "shopkeeper",
905 "wand", "ring", "amulet"
906};
907
908#define NSTR lenof(strings)
909
febd9a0f 910int main(void) {
2d56b16f 911 int in[NSTR];
912 int i, j;
913 unsigned seed = 0;
914
915 for (i = 0; i < NSTR; i++) in[i] = 0;
916 array = NULL;
917 arraylen = arraysize = 0;
918 tree = newtree234(mycmp);
919 cmp = mycmp;
920
921 verify();
922 for (i = 0; i < 10000; i++) {
923 j = randomnumber(&seed);
924 j %= NSTR;
925 printf("trial: %d\n", i);
926 if (in[j]) {
927 printf("deleting %s (%d)\n", strings[j], j);
928 deltest(strings[j]);
929 in[j] = 0;
930 } else {
931 printf("adding %s (%d)\n", strings[j], j);
932 addtest(strings[j]);
933 in[j] = 1;
934 }
935 }
936
937 while (arraylen > 0) {
938 j = randomnumber(&seed);
939 j %= arraylen;
940 deltest(array[j]);
941 }
942
943 return 0;
febd9a0f 944}
2d56b16f 945
febd9a0f 946#endif