Wez Furlong's patch to add xterm mouse reporting and proper mouse
[u/mdw/putty] / tree234.c
CommitLineData
febd9a0f 1/*
d2371c81 2 * tree234.c: reasonably generic counted 2-3-4 tree routines.
3 *
4 * This file is copyright 1999-2001 Simon Tatham.
5 *
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software and associated documentation
8 * files (the "Software"), to deal in the Software without
9 * restriction, including without limitation the rights to use,
10 * copy, modify, merge, publish, distribute, sublicense, and/or
11 * sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following
13 * conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL SIMON TATHAM BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
febd9a0f 26 */
27
28#include <stdio.h>
29#include <stdlib.h>
d2371c81 30#include <assert.h>
dcbde236 31
febd9a0f 32#include "tree234.h"
33
d2371c81 34#define smalloc malloc
35#define sfree free
36
dcbde236 37#define mknew(typ) ( (typ *) smalloc (sizeof (typ)) )
febd9a0f 38
39#ifdef TEST
40#define LOG(x) (printf x)
41#else
cdd6c586 42#define LOG(x)
febd9a0f 43#endif
44
d2371c81 45typedef struct node234_Tag node234;
46
febd9a0f 47struct tree234_Tag {
48 node234 *root;
49 cmpfn234 cmp;
50};
51
52struct node234_Tag {
53 node234 *parent;
54 node234 *kids[4];
d2371c81 55 int counts[4];
febd9a0f 56 void *elems[3];
57};
58
59/*
60 * Create a 2-3-4 tree.
61 */
62tree234 *newtree234(cmpfn234 cmp) {
63 tree234 *ret = mknew(tree234);
64 LOG(("created tree %p\n", ret));
65 ret->root = NULL;
66 ret->cmp = cmp;
67 return ret;
68}
69
70/*
71 * Free a 2-3-4 tree (not including freeing the elements).
72 */
73static void freenode234(node234 *n) {
74 if (!n)
75 return;
76 freenode234(n->kids[0]);
77 freenode234(n->kids[1]);
78 freenode234(n->kids[2]);
79 freenode234(n->kids[3]);
80 sfree(n);
81}
82void freetree234(tree234 *t) {
83 freenode234(t->root);
84 sfree(t);
85}
86
87/*
d2371c81 88 * Internal function to count a node.
89 */
90static int countnode234(node234 *n) {
91 int count = 0;
92 int i;
c404e5b3 93 if (!n)
94 return 0;
d2371c81 95 for (i = 0; i < 4; i++)
96 count += n->counts[i];
97 for (i = 0; i < 3; i++)
98 if (n->elems[i])
99 count++;
100 return count;
101}
102
103/*
104 * Count the elements in a tree.
105 */
106int count234(tree234 *t) {
107 if (t->root)
108 return countnode234(t->root);
109 else
110 return 0;
111}
112
113/*
febd9a0f 114 * Add an element e to a 2-3-4 tree t. Returns e on success, or if
115 * an existing element compares equal, returns that.
116 */
d2371c81 117static void *add234_internal(tree234 *t, void *e, int index) {
febd9a0f 118 node234 *n, **np, *left, *right;
119 void *orig_e = e;
d2371c81 120 int c, lcount, rcount;
febd9a0f 121
122 LOG(("adding node %p to tree %p\n", e, t));
123 if (t->root == NULL) {
124 t->root = mknew(node234);
125 t->root->elems[1] = t->root->elems[2] = NULL;
126 t->root->kids[0] = t->root->kids[1] = NULL;
127 t->root->kids[2] = t->root->kids[3] = NULL;
d2371c81 128 t->root->counts[0] = t->root->counts[1] = 0;
129 t->root->counts[2] = t->root->counts[3] = 0;
febd9a0f 130 t->root->parent = NULL;
131 t->root->elems[0] = e;
132 LOG((" created root %p\n", t->root));
133 return orig_e;
134 }
135
136 np = &t->root;
137 while (*np) {
d2371c81 138 int childnum;
febd9a0f 139 n = *np;
d2371c81 140 LOG((" node %p: %p/%d [%p] %p/%d [%p] %p/%d [%p] %p/%d\n",
141 n,
142 n->kids[0], n->counts[0], n->elems[0],
143 n->kids[1], n->counts[1], n->elems[1],
144 n->kids[2], n->counts[2], n->elems[2],
145 n->kids[3], n->counts[3]));
146 if (index >= 0) {
147 if (!n->kids[0]) {
148 /*
149 * Leaf node. We want to insert at kid position
150 * equal to the index:
151 *
152 * 0 A 1 B 2 C 3
153 */
154 childnum = index;
155 } else {
156 /*
157 * Internal node. We always descend through it (add
158 * always starts at the bottom, never in the
159 * middle).
160 */
161 do { /* this is a do ... while (0) to allow `break' */
162 if (index <= n->counts[0]) {
163 childnum = 0;
164 break;
165 }
166 index -= n->counts[0] + 1;
167 if (index <= n->counts[1]) {
168 childnum = 1;
169 break;
170 }
171 index -= n->counts[1] + 1;
172 if (index <= n->counts[2]) {
173 childnum = 2;
174 break;
175 }
176 index -= n->counts[2] + 1;
177 if (index <= n->counts[3]) {
178 childnum = 3;
179 break;
180 }
181 return NULL; /* error: index out of range */
182 } while (0);
183 }
184 } else {
185 if ((c = t->cmp(e, n->elems[0])) < 0)
186 childnum = 0;
187 else if (c == 0)
188 return n->elems[0]; /* already exists */
189 else if (n->elems[1] == NULL || (c = t->cmp(e, n->elems[1])) < 0)
190 childnum = 1;
191 else if (c == 0)
192 return n->elems[1]; /* already exists */
193 else if (n->elems[2] == NULL || (c = t->cmp(e, n->elems[2])) < 0)
194 childnum = 2;
195 else if (c == 0)
196 return n->elems[2]; /* already exists */
197 else
198 childnum = 3;
199 }
200 np = &n->kids[childnum];
201 LOG((" moving to child %d (%p)\n", childnum, *np));
febd9a0f 202 }
203
204 /*
205 * We need to insert the new element in n at position np.
206 */
d2371c81 207 left = NULL; lcount = 0;
208 right = NULL; rcount = 0;
febd9a0f 209 while (n) {
d2371c81 210 LOG((" at %p: %p/%d [%p] %p/%d [%p] %p/%d [%p] %p/%d\n",
211 n,
212 n->kids[0], n->counts[0], n->elems[0],
213 n->kids[1], n->counts[1], n->elems[1],
214 n->kids[2], n->counts[2], n->elems[2],
215 n->kids[3], n->counts[3]));
216 LOG((" need to insert %p/%d [%p] %p/%d at position %d\n",
217 left, lcount, e, right, rcount, np - n->kids));
febd9a0f 218 if (n->elems[1] == NULL) {
219 /*
220 * Insert in a 2-node; simple.
221 */
222 if (np == &n->kids[0]) {
223 LOG((" inserting on left of 2-node\n"));
d2371c81 224 n->kids[2] = n->kids[1]; n->counts[2] = n->counts[1];
febd9a0f 225 n->elems[1] = n->elems[0];
d2371c81 226 n->kids[1] = right; n->counts[1] = rcount;
febd9a0f 227 n->elems[0] = e;
d2371c81 228 n->kids[0] = left; n->counts[0] = lcount;
febd9a0f 229 } else { /* np == &n->kids[1] */
230 LOG((" inserting on right of 2-node\n"));
d2371c81 231 n->kids[2] = right; n->counts[2] = rcount;
febd9a0f 232 n->elems[1] = e;
d2371c81 233 n->kids[1] = left; n->counts[1] = lcount;
febd9a0f 234 }
235 if (n->kids[0]) n->kids[0]->parent = n;
236 if (n->kids[1]) n->kids[1]->parent = n;
237 if (n->kids[2]) n->kids[2]->parent = n;
238 LOG((" done\n"));
239 break;
240 } else if (n->elems[2] == NULL) {
241 /*
242 * Insert in a 3-node; simple.
243 */
244 if (np == &n->kids[0]) {
245 LOG((" inserting on left of 3-node\n"));
d2371c81 246 n->kids[3] = n->kids[2]; n->counts[3] = n->counts[2];
febd9a0f 247 n->elems[2] = n->elems[1];
d2371c81 248 n->kids[2] = n->kids[1]; n->counts[2] = n->counts[1];
febd9a0f 249 n->elems[1] = n->elems[0];
d2371c81 250 n->kids[1] = right; n->counts[1] = rcount;
febd9a0f 251 n->elems[0] = e;
d2371c81 252 n->kids[0] = left; n->counts[0] = lcount;
febd9a0f 253 } else if (np == &n->kids[1]) {
254 LOG((" inserting in middle of 3-node\n"));
d2371c81 255 n->kids[3] = n->kids[2]; n->counts[3] = n->counts[2];
febd9a0f 256 n->elems[2] = n->elems[1];
d2371c81 257 n->kids[2] = right; n->counts[2] = rcount;
febd9a0f 258 n->elems[1] = e;
d2371c81 259 n->kids[1] = left; n->counts[1] = lcount;
febd9a0f 260 } else { /* np == &n->kids[2] */
261 LOG((" inserting on right of 3-node\n"));
d2371c81 262 n->kids[3] = right; n->counts[3] = rcount;
febd9a0f 263 n->elems[2] = e;
d2371c81 264 n->kids[2] = left; n->counts[2] = lcount;
febd9a0f 265 }
266 if (n->kids[0]) n->kids[0]->parent = n;
267 if (n->kids[1]) n->kids[1]->parent = n;
268 if (n->kids[2]) n->kids[2]->parent = n;
269 if (n->kids[3]) n->kids[3]->parent = n;
270 LOG((" done\n"));
271 break;
272 } else {
273 node234 *m = mknew(node234);
274 m->parent = n->parent;
275 LOG((" splitting a 4-node; created new node %p\n", m));
276 /*
277 * Insert in a 4-node; split into a 2-node and a
278 * 3-node, and move focus up a level.
279 *
280 * I don't think it matters which way round we put the
281 * 2 and the 3. For simplicity, we'll put the 3 first
282 * always.
283 */
284 if (np == &n->kids[0]) {
d2371c81 285 m->kids[0] = left; m->counts[0] = lcount;
febd9a0f 286 m->elems[0] = e;
d2371c81 287 m->kids[1] = right; m->counts[1] = rcount;
febd9a0f 288 m->elems[1] = n->elems[0];
d2371c81 289 m->kids[2] = n->kids[1]; m->counts[2] = n->counts[1];
febd9a0f 290 e = n->elems[1];
d2371c81 291 n->kids[0] = n->kids[2]; n->counts[0] = n->counts[2];
febd9a0f 292 n->elems[0] = n->elems[2];
d2371c81 293 n->kids[1] = n->kids[3]; n->counts[1] = n->counts[3];
febd9a0f 294 } else if (np == &n->kids[1]) {
d2371c81 295 m->kids[0] = n->kids[0]; m->counts[0] = n->counts[0];
febd9a0f 296 m->elems[0] = n->elems[0];
d2371c81 297 m->kids[1] = left; m->counts[1] = lcount;
febd9a0f 298 m->elems[1] = e;
d2371c81 299 m->kids[2] = right; m->counts[2] = rcount;
febd9a0f 300 e = n->elems[1];
d2371c81 301 n->kids[0] = n->kids[2]; n->counts[0] = n->counts[2];
febd9a0f 302 n->elems[0] = n->elems[2];
d2371c81 303 n->kids[1] = n->kids[3]; n->counts[1] = n->counts[3];
febd9a0f 304 } else if (np == &n->kids[2]) {
d2371c81 305 m->kids[0] = n->kids[0]; m->counts[0] = n->counts[0];
febd9a0f 306 m->elems[0] = n->elems[0];
d2371c81 307 m->kids[1] = n->kids[1]; m->counts[1] = n->counts[1];
febd9a0f 308 m->elems[1] = n->elems[1];
d2371c81 309 m->kids[2] = left; m->counts[2] = lcount;
febd9a0f 310 /* e = e; */
d2371c81 311 n->kids[0] = right; n->counts[0] = rcount;
febd9a0f 312 n->elems[0] = n->elems[2];
d2371c81 313 n->kids[1] = n->kids[3]; n->counts[1] = n->counts[3];
febd9a0f 314 } else { /* np == &n->kids[3] */
d2371c81 315 m->kids[0] = n->kids[0]; m->counts[0] = n->counts[0];
febd9a0f 316 m->elems[0] = n->elems[0];
d2371c81 317 m->kids[1] = n->kids[1]; m->counts[1] = n->counts[1];
febd9a0f 318 m->elems[1] = n->elems[1];
d2371c81 319 m->kids[2] = n->kids[2]; m->counts[2] = n->counts[2];
320 n->kids[0] = left; n->counts[0] = lcount;
febd9a0f 321 n->elems[0] = e;
d2371c81 322 n->kids[1] = right; n->counts[1] = rcount;
febd9a0f 323 e = n->elems[2];
324 }
325 m->kids[3] = n->kids[3] = n->kids[2] = NULL;
d2371c81 326 m->counts[3] = n->counts[3] = n->counts[2] = 0;
febd9a0f 327 m->elems[2] = n->elems[2] = n->elems[1] = NULL;
328 if (m->kids[0]) m->kids[0]->parent = m;
329 if (m->kids[1]) m->kids[1]->parent = m;
330 if (m->kids[2]) m->kids[2]->parent = m;
331 if (n->kids[0]) n->kids[0]->parent = n;
332 if (n->kids[1]) n->kids[1]->parent = n;
d2371c81 333 LOG((" left (%p): %p/%d [%p] %p/%d [%p] %p/%d\n", m,
334 m->kids[0], m->counts[0], m->elems[0],
335 m->kids[1], m->counts[1], m->elems[1],
336 m->kids[2], m->counts[2]));
337 LOG((" right (%p): %p/%d [%p] %p/%d\n", n,
338 n->kids[0], n->counts[0], n->elems[0],
339 n->kids[1], n->counts[1]));
340 left = m; lcount = countnode234(left);
341 right = n; rcount = countnode234(right);
febd9a0f 342 }
343 if (n->parent)
344 np = (n->parent->kids[0] == n ? &n->parent->kids[0] :
345 n->parent->kids[1] == n ? &n->parent->kids[1] :
346 n->parent->kids[2] == n ? &n->parent->kids[2] :
347 &n->parent->kids[3]);
348 n = n->parent;
349 }
350
351 /*
352 * If we've come out of here by `break', n will still be
d2371c81 353 * non-NULL and all we need to do is go back up the tree
354 * updating counts. If we've come here because n is NULL, we
355 * need to create a new root for the tree because the old one
356 * has just split into two. */
357 if (n) {
358 while (n->parent) {
359 int count = countnode234(n);
360 int childnum;
361 childnum = (n->parent->kids[0] == n ? 0 :
362 n->parent->kids[1] == n ? 1 :
363 n->parent->kids[2] == n ? 2 : 3);
364 n->parent->counts[childnum] = count;
365 n = n->parent;
366 }
367 } else {
febd9a0f 368 LOG((" root is overloaded, split into two\n"));
369 t->root = mknew(node234);
d2371c81 370 t->root->kids[0] = left; t->root->counts[0] = lcount;
febd9a0f 371 t->root->elems[0] = e;
d2371c81 372 t->root->kids[1] = right; t->root->counts[1] = rcount;
febd9a0f 373 t->root->elems[1] = NULL;
d2371c81 374 t->root->kids[2] = NULL; t->root->counts[2] = 0;
febd9a0f 375 t->root->elems[2] = NULL;
d2371c81 376 t->root->kids[3] = NULL; t->root->counts[3] = 0;
febd9a0f 377 t->root->parent = NULL;
378 if (t->root->kids[0]) t->root->kids[0]->parent = t->root;
379 if (t->root->kids[1]) t->root->kids[1]->parent = t->root;
d2371c81 380 LOG((" new root is %p/%d [%p] %p/%d\n",
381 t->root->kids[0], t->root->counts[0],
382 t->root->elems[0],
383 t->root->kids[1], t->root->counts[1]));
febd9a0f 384 }
385
386 return orig_e;
387}
388
d2371c81 389void *add234(tree234 *t, void *e) {
390 if (!t->cmp) /* tree is unsorted */
391 return NULL;
392
393 return add234_internal(t, e, -1);
394}
395void *addpos234(tree234 *t, void *e, int index) {
396 if (index < 0 || /* index out of range */
397 t->cmp) /* tree is sorted */
398 return NULL; /* return failure */
399
400 return add234_internal(t, e, index); /* this checks the upper bound */
401}
402
febd9a0f 403/*
d2371c81 404 * Look up the element at a given numeric index in a 2-3-4 tree.
405 * Returns NULL if the index is out of range.
febd9a0f 406 */
d2371c81 407void *index234(tree234 *t, int index) {
febd9a0f 408 node234 *n;
febd9a0f 409
d2371c81 410 if (!t->root)
411 return NULL; /* tree is empty */
febd9a0f 412
d2371c81 413 if (index < 0 || index >= countnode234(t->root))
414 return NULL; /* out of range */
febd9a0f 415
416 n = t->root;
d2371c81 417
febd9a0f 418 while (n) {
d2371c81 419 if (index < n->counts[0])
febd9a0f 420 n = n->kids[0];
d2371c81 421 else if (index -= n->counts[0] + 1, index < 0)
febd9a0f 422 return n->elems[0];
d2371c81 423 else if (index < n->counts[1])
febd9a0f 424 n = n->kids[1];
d2371c81 425 else if (index -= n->counts[1] + 1, index < 0)
febd9a0f 426 return n->elems[1];
d2371c81 427 else if (index < n->counts[2])
febd9a0f 428 n = n->kids[2];
d2371c81 429 else if (index -= n->counts[2] + 1, index < 0)
febd9a0f 430 return n->elems[2];
431 else
432 n = n->kids[3];
433 }
434
d2371c81 435 /* We shouldn't ever get here. I wonder how we did. */
436 return NULL;
437}
438
439/*
440 * Find an element e in a sorted 2-3-4 tree t. Returns NULL if not
441 * found. e is always passed as the first argument to cmp, so cmp
442 * can be an asymmetric function if desired. cmp can also be passed
443 * as NULL, in which case the compare function from the tree proper
444 * will be used.
445 */
446void *findrelpos234(tree234 *t, void *e, cmpfn234 cmp,
447 int relation, int *index) {
448 node234 *n;
449 void *ret;
450 int c;
451 int idx, ecount, kcount, cmpret;
452
453 if (t->root == NULL)
454 return NULL;
455
456 if (cmp == NULL)
457 cmp = t->cmp;
458
459 n = t->root;
febd9a0f 460 /*
d2371c81 461 * Attempt to find the element itself.
febd9a0f 462 */
d2371c81 463 idx = 0;
464 ecount = -1;
465 /*
466 * Prepare a fake `cmp' result if e is NULL.
467 */
468 cmpret = 0;
469 if (e == NULL) {
470 assert(relation == REL234_LT || relation == REL234_GT);
471 if (relation == REL234_LT)
472 cmpret = +1; /* e is a max: always greater */
473 else if (relation == REL234_GT)
474 cmpret = -1; /* e is a min: always smaller */
475 }
476 while (1) {
477 for (kcount = 0; kcount < 4; kcount++) {
478 if (kcount >= 3 || n->elems[kcount] == NULL ||
479 (c = cmpret ? cmpret : cmp(e, n->elems[kcount])) < 0) {
480 break;
481 }
482 if (n->kids[kcount]) idx += n->counts[kcount];
483 if (c == 0) {
484 ecount = kcount;
485 break;
486 }
487 idx++;
488 }
489 if (ecount >= 0)
490 break;
491 if (n->kids[kcount])
492 n = n->kids[kcount];
493 else
494 break;
495 }
496
497 if (ecount >= 0) {
498 /*
499 * We have found the element we're looking for. It's
500 * n->elems[ecount], at tree index idx. If our search
501 * relation is EQ, LE or GE we can now go home.
502 */
503 if (relation != REL234_LT && relation != REL234_GT) {
504 if (index) *index = idx;
505 return n->elems[ecount];
506 }
507
508 /*
509 * Otherwise, we'll do an indexed lookup for the previous
510 * or next element. (It would be perfectly possible to
511 * implement these search types in a non-counted tree by
512 * going back up from where we are, but far more fiddly.)
513 */
514 if (relation == REL234_LT)
515 idx--;
516 else
517 idx++;
518 } else {
519 /*
520 * We've found our way to the bottom of the tree and we
521 * know where we would insert this node if we wanted to:
522 * we'd put it in in place of the (empty) subtree
523 * n->kids[kcount], and it would have index idx
524 *
525 * But the actual element isn't there. So if our search
526 * relation is EQ, we're doomed.
527 */
528 if (relation == REL234_EQ)
529 return NULL;
530
531 /*
532 * Otherwise, we must do an index lookup for index idx-1
533 * (if we're going left - LE or LT) or index idx (if we're
534 * going right - GE or GT).
535 */
536 if (relation == REL234_LT || relation == REL234_LE) {
537 idx--;
538 }
539 }
540
541 /*
542 * We know the index of the element we want; just call index234
543 * to do the rest. This will return NULL if the index is out of
544 * bounds, which is exactly what we want.
545 */
546 ret = index234(t, idx);
547 if (ret && index) *index = idx;
548 return ret;
549}
550void *find234(tree234 *t, void *e, cmpfn234 cmp) {
551 return findrelpos234(t, e, cmp, REL234_EQ, NULL);
552}
553void *findrel234(tree234 *t, void *e, cmpfn234 cmp, int relation) {
554 return findrelpos234(t, e, cmp, relation, NULL);
555}
556void *findpos234(tree234 *t, void *e, cmpfn234 cmp, int *index) {
557 return findrelpos234(t, e, cmp, REL234_EQ, index);
febd9a0f 558}
559
560/*
561 * Delete an element e in a 2-3-4 tree. Does not free the element,
562 * merely removes all links to it from the tree nodes.
563 */
d2371c81 564static void *delpos234_internal(tree234 *t, int index) {
febd9a0f 565 node234 *n;
d2371c81 566 void *retval;
febd9a0f 567 int ei = -1;
568
d2371c81 569 retval = 0;
570
febd9a0f 571 n = t->root;
d2371c81 572 LOG(("deleting item %d from tree %p\n", index, t));
febd9a0f 573 while (1) {
574 while (n) {
febd9a0f 575 int ki;
576 node234 *sub;
577
d2371c81 578 LOG((" node %p: %p/%d [%p] %p/%d [%p] %p/%d [%p] %p/%d index=%d\n",
579 n,
580 n->kids[0], n->counts[0], n->elems[0],
581 n->kids[1], n->counts[1], n->elems[1],
582 n->kids[2], n->counts[2], n->elems[2],
583 n->kids[3], n->counts[3],
584 index));
585 if (index < n->counts[0]) {
febd9a0f 586 ki = 0;
d2371c81 587 } else if (index -= n->counts[0]+1, index < 0) {
febd9a0f 588 ei = 0; break;
d2371c81 589 } else if (index < n->counts[1]) {
febd9a0f 590 ki = 1;
d2371c81 591 } else if (index -= n->counts[1]+1, index < 0) {
febd9a0f 592 ei = 1; break;
d2371c81 593 } else if (index < n->counts[2]) {
febd9a0f 594 ki = 2;
d2371c81 595 } else if (index -= n->counts[2]+1, index < 0) {
febd9a0f 596 ei = 2; break;
597 } else {
598 ki = 3;
599 }
600 /*
601 * Recurse down to subtree ki. If it has only one element,
602 * we have to do some transformation to start with.
603 */
604 LOG((" moving to subtree %d\n", ki));
605 sub = n->kids[ki];
606 if (!sub->elems[1]) {
607 LOG((" subtree has only one element!\n", ki));
608 if (ki > 0 && n->kids[ki-1]->elems[1]) {
609 /*
610 * Case 3a, left-handed variant. Child ki has
611 * only one element, but child ki-1 has two or
612 * more. So we need to move a subtree from ki-1
613 * to ki.
614 *
615 * . C . . B .
616 * / \ -> / \
617 * [more] a A b B c d D e [more] a A b c C d D e
618 */
619 node234 *sib = n->kids[ki-1];
620 int lastelem = (sib->elems[2] ? 2 :
621 sib->elems[1] ? 1 : 0);
622 sub->kids[2] = sub->kids[1];
d2371c81 623 sub->counts[2] = sub->counts[1];
febd9a0f 624 sub->elems[1] = sub->elems[0];
625 sub->kids[1] = sub->kids[0];
d2371c81 626 sub->counts[1] = sub->counts[0];
febd9a0f 627 sub->elems[0] = n->elems[ki-1];
628 sub->kids[0] = sib->kids[lastelem+1];
d2371c81 629 sub->counts[0] = sib->counts[lastelem+1];
100122a9 630 if (sub->kids[0]) sub->kids[0]->parent = sub;
febd9a0f 631 n->elems[ki-1] = sib->elems[lastelem];
632 sib->kids[lastelem+1] = NULL;
d2371c81 633 sib->counts[lastelem+1] = 0;
febd9a0f 634 sib->elems[lastelem] = NULL;
d2371c81 635 n->counts[ki] = countnode234(sub);
febd9a0f 636 LOG((" case 3a left\n"));
d2371c81 637 LOG((" index and left subtree count before adjustment: %d, %d\n",
638 index, n->counts[ki-1]));
639 index += n->counts[ki-1];
640 n->counts[ki-1] = countnode234(sib);
641 index -= n->counts[ki-1];
642 LOG((" index and left subtree count after adjustment: %d, %d\n",
643 index, n->counts[ki-1]));
febd9a0f 644 } else if (ki < 3 && n->kids[ki+1] &&
645 n->kids[ki+1]->elems[1]) {
646 /*
647 * Case 3a, right-handed variant. ki has only
648 * one element but ki+1 has two or more. Move a
649 * subtree from ki+1 to ki.
650 *
651 * . B . . C .
652 * / \ -> / \
653 * a A b c C d D e [more] a A b B c d D e [more]
654 */
655 node234 *sib = n->kids[ki+1];
656 int j;
657 sub->elems[1] = n->elems[ki];
658 sub->kids[2] = sib->kids[0];
d2371c81 659 sub->counts[2] = sib->counts[0];
100122a9 660 if (sub->kids[2]) sub->kids[2]->parent = sub;
febd9a0f 661 n->elems[ki] = sib->elems[0];
662 sib->kids[0] = sib->kids[1];
d2371c81 663 sib->counts[0] = sib->counts[1];
febd9a0f 664 for (j = 0; j < 2 && sib->elems[j+1]; j++) {
665 sib->kids[j+1] = sib->kids[j+2];
d2371c81 666 sib->counts[j+1] = sib->counts[j+2];
febd9a0f 667 sib->elems[j] = sib->elems[j+1];
668 }
669 sib->kids[j+1] = NULL;
d2371c81 670 sib->counts[j+1] = 0;
febd9a0f 671 sib->elems[j] = NULL;
d2371c81 672 n->counts[ki] = countnode234(sub);
673 n->counts[ki+1] = countnode234(sib);
febd9a0f 674 LOG((" case 3a right\n"));
675 } else {
676 /*
677 * Case 3b. ki has only one element, and has no
678 * neighbour with more than one. So pick a
679 * neighbour and merge it with ki, taking an
680 * element down from n to go in the middle.
681 *
682 * . B . .
683 * / \ -> |
684 * a A b c C d a A b B c C d
685 *
686 * (Since at all points we have avoided
687 * descending to a node with only one element,
688 * we can be sure that n is not reduced to
689 * nothingness by this move, _unless_ it was
690 * the very first node, ie the root of the
691 * tree. In that case we remove the now-empty
692 * root and replace it with its single large
693 * child as shown.)
694 */
695 node234 *sib;
696 int j;
697
d2371c81 698 if (ki > 0) {
febd9a0f 699 ki--;
d2371c81 700 index += n->counts[ki] + 1;
701 }
febd9a0f 702 sib = n->kids[ki];
703 sub = n->kids[ki+1];
704
705 sub->kids[3] = sub->kids[1];
d2371c81 706 sub->counts[3] = sub->counts[1];
febd9a0f 707 sub->elems[2] = sub->elems[0];
708 sub->kids[2] = sub->kids[0];
d2371c81 709 sub->counts[2] = sub->counts[0];
febd9a0f 710 sub->elems[1] = n->elems[ki];
711 sub->kids[1] = sib->kids[1];
d2371c81 712 sub->counts[1] = sib->counts[1];
100122a9 713 if (sub->kids[1]) sub->kids[1]->parent = sub;
febd9a0f 714 sub->elems[0] = sib->elems[0];
715 sub->kids[0] = sib->kids[0];
d2371c81 716 sub->counts[0] = sib->counts[0];
100122a9 717 if (sub->kids[0]) sub->kids[0]->parent = sub;
febd9a0f 718
d2371c81 719 n->counts[ki+1] = countnode234(sub);
720
febd9a0f 721 sfree(sib);
722
723 /*
724 * That's built the big node in sub. Now we
725 * need to remove the reference to sib in n.
726 */
727 for (j = ki; j < 3 && n->kids[j+1]; j++) {
728 n->kids[j] = n->kids[j+1];
d2371c81 729 n->counts[j] = n->counts[j+1];
febd9a0f 730 n->elems[j] = j<2 ? n->elems[j+1] : NULL;
731 }
732 n->kids[j] = NULL;
d2371c81 733 n->counts[j] = 0;
febd9a0f 734 if (j < 3) n->elems[j] = NULL;
2d56b16f 735 LOG((" case 3b ki=%d\n", ki));
febd9a0f 736
737 if (!n->elems[0]) {
738 /*
739 * The root is empty and needs to be
740 * removed.
741 */
742 LOG((" shifting root!\n"));
743 t->root = sub;
744 sub->parent = NULL;
745 sfree(n);
746 }
747 }
748 }
749 n = sub;
750 }
d2371c81 751 if (!retval)
752 retval = n->elems[ei];
753
febd9a0f 754 if (ei==-1)
d2371c81 755 return NULL; /* although this shouldn't happen */
febd9a0f 756
757 /*
758 * Treat special case: this is the one remaining item in
759 * the tree. n is the tree root (no parent), has one
760 * element (no elems[1]), and has no kids (no kids[0]).
761 */
762 if (!n->parent && !n->elems[1] && !n->kids[0]) {
763 LOG((" removed last element in tree\n"));
764 sfree(n);
765 t->root = NULL;
d2371c81 766 return retval;
febd9a0f 767 }
768
769 /*
770 * Now we have the element we want, as n->elems[ei], and we
771 * have also arranged for that element not to be the only
772 * one in its node. So...
773 */
774
775 if (!n->kids[0] && n->elems[1]) {
776 /*
777 * Case 1. n is a leaf node with more than one element,
778 * so it's _really easy_. Just delete the thing and
779 * we're done.
780 */
781 int i;
782 LOG((" case 1\n"));
a4a19e73 783 for (i = ei; i < 2 && n->elems[i+1]; i++)
febd9a0f 784 n->elems[i] = n->elems[i+1];
785 n->elems[i] = NULL;
d2371c81 786 /*
787 * Having done that to the leaf node, we now go back up
788 * the tree fixing the counts.
789 */
790 while (n->parent) {
791 int childnum;
792 childnum = (n->parent->kids[0] == n ? 0 :
793 n->parent->kids[1] == n ? 1 :
794 n->parent->kids[2] == n ? 2 : 3);
795 n->parent->counts[childnum]--;
796 n = n->parent;
797 }
798 return retval; /* finished! */
febd9a0f 799 } else if (n->kids[ei]->elems[1]) {
800 /*
801 * Case 2a. n is an internal node, and the root of the
802 * subtree to the left of e has more than one element.
803 * So find the predecessor p to e (ie the largest node
804 * in that subtree), place it where e currently is, and
805 * then start the deletion process over again on the
806 * subtree with p as target.
807 */
808 node234 *m = n->kids[ei];
809 void *target;
810 LOG((" case 2a\n"));
811 while (m->kids[0]) {
812 m = (m->kids[3] ? m->kids[3] :
813 m->kids[2] ? m->kids[2] :
814 m->kids[1] ? m->kids[1] : m->kids[0]);
815 }
816 target = (m->elems[2] ? m->elems[2] :
817 m->elems[1] ? m->elems[1] : m->elems[0]);
818 n->elems[ei] = target;
d2371c81 819 index = n->counts[ei]-1;
febd9a0f 820 n = n->kids[ei];
febd9a0f 821 } else if (n->kids[ei+1]->elems[1]) {
822 /*
823 * Case 2b, symmetric to 2a but s/left/right/ and
824 * s/predecessor/successor/. (And s/largest/smallest/).
825 */
826 node234 *m = n->kids[ei+1];
827 void *target;
828 LOG((" case 2b\n"));
829 while (m->kids[0]) {
830 m = m->kids[0];
831 }
832 target = m->elems[0];
833 n->elems[ei] = target;
834 n = n->kids[ei+1];
d2371c81 835 index = 0;
febd9a0f 836 } else {
837 /*
838 * Case 2c. n is an internal node, and the subtrees to
839 * the left and right of e both have only one element.
840 * So combine the two subnodes into a single big node
841 * with their own elements on the left and right and e
842 * in the middle, then restart the deletion process on
843 * that subtree, with e still as target.
844 */
845 node234 *a = n->kids[ei], *b = n->kids[ei+1];
846 int j;
847
848 LOG((" case 2c\n"));
849 a->elems[1] = n->elems[ei];
850 a->kids[2] = b->kids[0];
d2371c81 851 a->counts[2] = b->counts[0];
100122a9 852 if (a->kids[2]) a->kids[2]->parent = a;
febd9a0f 853 a->elems[2] = b->elems[0];
854 a->kids[3] = b->kids[1];
d2371c81 855 a->counts[3] = b->counts[1];
100122a9 856 if (a->kids[3]) a->kids[3]->parent = a;
febd9a0f 857 sfree(b);
d2371c81 858 n->counts[ei] = countnode234(a);
febd9a0f 859 /*
860 * That's built the big node in a, and destroyed b. Now
861 * remove the reference to b (and e) in n.
862 */
863 for (j = ei; j < 2 && n->elems[j+1]; j++) {
864 n->elems[j] = n->elems[j+1];
865 n->kids[j+1] = n->kids[j+2];
d2371c81 866 n->counts[j+1] = n->counts[j+2];
febd9a0f 867 }
868 n->elems[j] = NULL;
869 n->kids[j+1] = NULL;
d2371c81 870 n->counts[j+1] = 0;
e9e9556d 871 /*
872 * It's possible, in this case, that we've just removed
873 * the only element in the root of the tree. If so,
874 * shift the root.
875 */
876 if (n->elems[0] == NULL) {
877 LOG((" shifting root!\n"));
878 t->root = a;
879 a->parent = NULL;
880 sfree(n);
881 }
febd9a0f 882 /*
883 * Now go round the deletion process again, with n
884 * pointing at the new big node and e still the same.
885 */
886 n = a;
d2371c81 887 index = a->counts[0] + a->counts[1] + 1;
febd9a0f 888 }
889 }
890}
d2371c81 891void *delpos234(tree234 *t, int index) {
892 if (index < 0 || index >= countnode234(t->root))
febd9a0f 893 return NULL;
d2371c81 894 return delpos234_internal(t, index);
febd9a0f 895}
d2371c81 896void *del234(tree234 *t, void *e) {
897 int index;
898 if (!findrelpos234(t, e, NULL, REL234_EQ, &index))
899 return NULL; /* it wasn't in there anyway */
900 return delpos234_internal(t, index); /* it's there; delete it. */
febd9a0f 901}
902
903#ifdef TEST
904
2d56b16f 905/*
906 * Test code for the 2-3-4 tree. This code maintains an alternative
907 * representation of the data in the tree, in an array (using the
908 * obvious and slow insert and delete functions). After each tree
7aa7c43a 909 * operation, the verify() function is called, which ensures all
d2371c81 910 * the tree properties are preserved:
911 * - node->child->parent always equals node
912 * - tree->root->parent always equals NULL
913 * - number of kids == 0 or number of elements + 1;
914 * - tree has the same depth everywhere
915 * - every node has at least one element
916 * - subtree element counts are accurate
917 * - any NULL kid pointer is accompanied by a zero count
918 * - in a sorted tree: ordering property between elements of a
919 * node and elements of its children is preserved
920 * and also ensures the list represented by the tree is the same
921 * list it should be. (This last check also doubly verifies the
922 * ordering properties, because the `same list it should be' is by
923 * definition correctly ordered. It also ensures all nodes are
924 * distinct, because the enum functions would get caught in a loop
925 * if not.)
2d56b16f 926 */
927
928#include <stdarg.h>
929
d2371c81 930#define srealloc realloc
931
2d56b16f 932/*
933 * Error reporting function.
934 */
935void error(char *fmt, ...) {
936 va_list ap;
937 printf("ERROR: ");
938 va_start(ap, fmt);
939 vfprintf(stdout, fmt, ap);
940 va_end(ap);
941 printf("\n");
942}
943
944/* The array representation of the data. */
945void **array;
946int arraylen, arraysize;
947cmpfn234 cmp;
948
949/* The tree representation of the same data. */
950tree234 *tree;
951
952typedef struct {
953 int treedepth;
954 int elemcount;
955} chkctx;
956
d2371c81 957int chknode(chkctx *ctx, int level, node234 *node,
2d56b16f 958 void *lowbound, void *highbound) {
959 int nkids, nelems;
960 int i;
d2371c81 961 int count;
2d56b16f 962
963 /* Count the non-NULL kids. */
964 for (nkids = 0; nkids < 4 && node->kids[nkids]; nkids++);
965 /* Ensure no kids beyond the first NULL are non-NULL. */
966 for (i = nkids; i < 4; i++)
967 if (node->kids[i]) {
968 error("node %p: nkids=%d but kids[%d] non-NULL",
969 node, nkids, i);
d2371c81 970 } else if (node->counts[i]) {
971 error("node %p: kids[%d] NULL but count[%d]=%d nonzero",
972 node, i, i, node->counts[i]);
973 }
2d56b16f 974
975 /* Count the non-NULL elements. */
976 for (nelems = 0; nelems < 3 && node->elems[nelems]; nelems++);
977 /* Ensure no elements beyond the first NULL are non-NULL. */
978 for (i = nelems; i < 3; i++)
979 if (node->elems[i]) {
980 error("node %p: nelems=%d but elems[%d] non-NULL",
981 node, nelems, i);
982 }
983
984 if (nkids == 0) {
985 /*
986 * If nkids==0, this is a leaf node; verify that the tree
987 * depth is the same everywhere.
988 */
989 if (ctx->treedepth < 0)
990 ctx->treedepth = level; /* we didn't know the depth yet */
991 else if (ctx->treedepth != level)
992 error("node %p: leaf at depth %d, previously seen depth %d",
993 node, level, ctx->treedepth);
994 } else {
995 /*
996 * If nkids != 0, then it should be nelems+1, unless nelems
997 * is 0 in which case nkids should also be 0 (and so we
998 * shouldn't be in this condition at all).
999 */
1000 int shouldkids = (nelems ? nelems+1 : 0);
1001 if (nkids != shouldkids) {
1002 error("node %p: %d elems should mean %d kids but has %d",
1003 node, nelems, shouldkids, nkids);
1004 }
1005 }
1006
1007 /*
1008 * nelems should be at least 1.
1009 */
1010 if (nelems == 0) {
1011 error("node %p: no elems", node, nkids);
1012 }
1013
1014 /*
d2371c81 1015 * Add nelems to the running element count of the whole tree.
2d56b16f 1016 */
1017 ctx->elemcount += nelems;
1018
1019 /*
1020 * Check ordering property: all elements should be strictly >
1021 * lowbound, strictly < highbound, and strictly < each other in
1022 * sequence. (lowbound and highbound are NULL at edges of tree
1023 * - both NULL at root node - and NULL is considered to be <
1024 * everything and > everything. IYSWIM.)
1025 */
d2371c81 1026 if (cmp) {
1027 for (i = -1; i < nelems; i++) {
1028 void *lower = (i == -1 ? lowbound : node->elems[i]);
1029 void *higher = (i+1 == nelems ? highbound : node->elems[i+1]);
1030 if (lower && higher && cmp(lower, higher) >= 0) {
1031 error("node %p: kid comparison [%d=%s,%d=%s] failed",
1032 node, i, lower, i+1, higher);
1033 }
1034 }
2d56b16f 1035 }
1036
1037 /*
1038 * Check parent pointers: all non-NULL kids should have a
1039 * parent pointer coming back to this node.
1040 */
1041 for (i = 0; i < nkids; i++)
1042 if (node->kids[i]->parent != node) {
1043 error("node %p kid %d: parent ptr is %p not %p",
1044 node, i, node->kids[i]->parent, node);
1045 }
1046
1047
1048 /*
1049 * Now (finally!) recurse into subtrees.
1050 */
d2371c81 1051 count = nelems;
1052
2d56b16f 1053 for (i = 0; i < nkids; i++) {
1054 void *lower = (i == 0 ? lowbound : node->elems[i-1]);
1055 void *higher = (i >= nelems ? highbound : node->elems[i]);
d2371c81 1056 int subcount = chknode(ctx, level+1, node->kids[i], lower, higher);
1057 if (node->counts[i] != subcount) {
1058 error("node %p kid %d: count says %d, subtree really has %d",
1059 node, i, node->counts[i], subcount);
1060 }
1061 count += subcount;
2d56b16f 1062 }
d2371c81 1063
1064 return count;
2d56b16f 1065}
1066
1067void verify(void) {
1068 chkctx ctx;
2d56b16f 1069 int i;
1070 void *p;
1071
1072 ctx.treedepth = -1; /* depth unknown yet */
1073 ctx.elemcount = 0; /* no elements seen yet */
1074 /*
1075 * Verify validity of tree properties.
1076 */
d2371c81 1077 if (tree->root) {
1078 if (tree->root->parent != NULL)
1079 error("root->parent is %p should be null", tree->root->parent);
2d56b16f 1080 chknode(&ctx, 0, tree->root, NULL, NULL);
d2371c81 1081 }
2d56b16f 1082 printf("tree depth: %d\n", ctx.treedepth);
1083 /*
1084 * Enumerate the tree and ensure it matches up to the array.
1085 */
d2371c81 1086 for (i = 0; NULL != (p = index234(tree, i)); i++) {
2d56b16f 1087 if (i >= arraylen)
1088 error("tree contains more than %d elements", arraylen);
1089 if (array[i] != p)
1090 error("enum at position %d: array says %s, tree says %s",
1091 i, array[i], p);
1092 }
d2371c81 1093 if (ctx.elemcount != i) {
2d56b16f 1094 error("tree really contains %d elements, enum gave %d",
d2371c81 1095 ctx.elemcount, i);
2d56b16f 1096 }
1097 if (i < arraylen) {
1098 error("enum gave only %d elements, array has %d", i, arraylen);
1099 }
d2371c81 1100 i = count234(tree);
1101 if (ctx.elemcount != i) {
1102 error("tree really contains %d elements, count234 gave %d",
1103 ctx.elemcount, i);
1104 }
2d56b16f 1105}
1106
d2371c81 1107void internal_addtest(void *elem, int index, void *realret) {
2d56b16f 1108 int i, j;
d2371c81 1109 void *retval;
2d56b16f 1110
1111 if (arraysize < arraylen+1) {
1112 arraysize = arraylen+1+256;
dcbde236 1113 array = (array == NULL ? smalloc(arraysize*sizeof(*array)) :
1114 srealloc(array, arraysize*sizeof(*array)));
2d56b16f 1115 }
1116
d2371c81 1117 i = index;
2d56b16f 1118 /* now i points to the first element >= elem */
d2371c81 1119 retval = elem; /* expect elem returned (success) */
1120 for (j = arraylen; j > i; j--)
1121 array[j] = array[j-1];
1122 array[i] = elem; /* add elem to array */
1123 arraylen++;
2d56b16f 1124
2d56b16f 1125 if (realret != retval) {
1126 error("add: retval was %p expected %p", realret, retval);
1127 }
1128
1129 verify();
1130}
1131
d2371c81 1132void addtest(void *elem) {
2d56b16f 1133 int i;
d2371c81 1134 void *realret;
1135
1136 realret = add234(tree, elem);
2d56b16f 1137
1138 i = 0;
1139 while (i < arraylen && cmp(elem, array[i]) > 0)
1140 i++;
d2371c81 1141 if (i < arraylen && !cmp(elem, array[i])) {
1142 void *retval = array[i]; /* expect that returned not elem */
1143 if (realret != retval) {
1144 error("add: retval was %p expected %p", realret, retval);
1145 }
1146 } else
1147 internal_addtest(elem, i, realret);
1148}
1149
1150void addpostest(void *elem, int i) {
1151 void *realret;
1152
1153 realret = addpos234(tree, elem, i);
1154
1155 internal_addtest(elem, i, realret);
1156}
1157
1158void delpostest(int i) {
1159 int index = i;
1160 void *elem = array[i], *ret;
1161
1162 /* i points to the right element */
1163 while (i < arraylen-1) {
1164 array[i] = array[i+1];
1165 i++;
2d56b16f 1166 }
d2371c81 1167 arraylen--; /* delete elem from array */
1168
1169 if (tree->cmp)
1170 ret = del234(tree, elem);
1171 else
1172 ret = delpos234(tree, index);
2d56b16f 1173
d2371c81 1174 if (ret != elem) {
1175 error("del returned %p, expected %p", ret, elem);
1176 }
2d56b16f 1177
1178 verify();
febd9a0f 1179}
2d56b16f 1180
d2371c81 1181void deltest(void *elem) {
1182 int i;
1183
1184 i = 0;
1185 while (i < arraylen && cmp(elem, array[i]) > 0)
1186 i++;
1187 if (i >= arraylen || cmp(elem, array[i]) != 0)
1188 return; /* don't do it! */
1189 delpostest(i);
1190}
1191
2d56b16f 1192/* A sample data set and test utility. Designed for pseudo-randomness,
1193 * and yet repeatability. */
1194
1195/*
1196 * This random number generator uses the `portable implementation'
1197 * given in ANSI C99 draft N869. It assumes `unsigned' is 32 bits;
1198 * change it if not.
1199 */
1200int randomnumber(unsigned *seed) {
1201 *seed *= 1103515245;
1202 *seed += 12345;
1203 return ((*seed) / 65536) % 32768;
febd9a0f 1204}
1205
2d56b16f 1206int mycmp(void *av, void *bv) {
1207 char const *a = (char const *)av;
1208 char const *b = (char const *)bv;
febd9a0f 1209 return strcmp(a, b);
1210}
1211
2d56b16f 1212#define lenof(x) ( sizeof((x)) / sizeof(*(x)) )
1213
1214char *strings[] = {
1215 "a", "ab", "absque", "coram", "de",
1216 "palam", "clam", "cum", "ex", "e",
1217 "sine", "tenus", "pro", "prae",
1218 "banana", "carrot", "cabbage", "broccoli", "onion", "zebra",
1219 "penguin", "blancmange", "pangolin", "whale", "hedgehog",
1220 "giraffe", "peanut", "bungee", "foo", "bar", "baz", "quux",
1221 "murfl", "spoo", "breen", "flarn", "octothorpe",
1222 "snail", "tiger", "elephant", "octopus", "warthog", "armadillo",
1223 "aardvark", "wyvern", "dragon", "elf", "dwarf", "orc", "goblin",
1224 "pixie", "basilisk", "warg", "ape", "lizard", "newt", "shopkeeper",
1225 "wand", "ring", "amulet"
1226};
1227
1228#define NSTR lenof(strings)
1229
d2371c81 1230int findtest(void) {
1231 const static int rels[] = {
1232 REL234_EQ, REL234_GE, REL234_LE, REL234_LT, REL234_GT
1233 };
1234 const static char *const relnames[] = {
1235 "EQ", "GE", "LE", "LT", "GT"
1236 };
1237 int i, j, rel, index;
1238 char *p, *ret, *realret, *realret2;
1239 int lo, hi, mid, c;
1240
1241 for (i = 0; i < NSTR; i++) {
1242 p = strings[i];
1243 for (j = 0; j < sizeof(rels)/sizeof(*rels); j++) {
1244 rel = rels[j];
1245
1246 lo = 0; hi = arraylen-1;
1247 while (lo <= hi) {
1248 mid = (lo + hi) / 2;
1249 c = strcmp(p, array[mid]);
1250 if (c < 0)
1251 hi = mid-1;
1252 else if (c > 0)
1253 lo = mid+1;
1254 else
1255 break;
1256 }
1257
1258 if (c == 0) {
1259 if (rel == REL234_LT)
1260 ret = (mid > 0 ? array[--mid] : NULL);
1261 else if (rel == REL234_GT)
1262 ret = (mid < arraylen-1 ? array[++mid] : NULL);
1263 else
1264 ret = array[mid];
1265 } else {
1266 assert(lo == hi+1);
1267 if (rel == REL234_LT || rel == REL234_LE) {
1268 mid = hi;
1269 ret = (hi >= 0 ? array[hi] : NULL);
1270 } else if (rel == REL234_GT || rel == REL234_GE) {
1271 mid = lo;
1272 ret = (lo < arraylen ? array[lo] : NULL);
1273 } else
1274 ret = NULL;
1275 }
1276
1277 realret = findrelpos234(tree, p, NULL, rel, &index);
1278 if (realret != ret) {
1279 error("find(\"%s\",%s) gave %s should be %s",
1280 p, relnames[j], realret, ret);
1281 }
1282 if (realret && index != mid) {
1283 error("find(\"%s\",%s) gave %d should be %d",
1284 p, relnames[j], index, mid);
1285 }
1286 if (realret && rel == REL234_EQ) {
1287 realret2 = index234(tree, index);
1288 if (realret2 != realret) {
1289 error("find(\"%s\",%s) gave %s(%d) but %d -> %s",
1290 p, relnames[j], realret, index, index, realret2);
1291 }
1292 }
1293#if 0
1294 printf("find(\"%s\",%s) gave %s(%d)\n", p, relnames[j],
1295 realret, index);
1296#endif
1297 }
1298 }
1299
1300 realret = findrelpos234(tree, NULL, NULL, REL234_GT, &index);
1301 if (arraylen && (realret != array[0] || index != 0)) {
1302 error("find(NULL,GT) gave %s(%d) should be %s(0)",
1303 realret, index, array[0]);
1304 } else if (!arraylen && (realret != NULL)) {
1305 error("find(NULL,GT) gave %s(%d) should be NULL",
1306 realret, index);
1307 }
1308
1309 realret = findrelpos234(tree, NULL, NULL, REL234_LT, &index);
1310 if (arraylen && (realret != array[arraylen-1] || index != arraylen-1)) {
1311 error("find(NULL,LT) gave %s(%d) should be %s(0)",
1312 realret, index, array[arraylen-1]);
1313 } else if (!arraylen && (realret != NULL)) {
1314 error("find(NULL,LT) gave %s(%d) should be NULL",
1315 realret, index);
1316 }
1317}
1318
febd9a0f 1319int main(void) {
2d56b16f 1320 int in[NSTR];
d2371c81 1321 int i, j, k;
2d56b16f 1322 unsigned seed = 0;
1323
1324 for (i = 0; i < NSTR; i++) in[i] = 0;
1325 array = NULL;
1326 arraylen = arraysize = 0;
1327 tree = newtree234(mycmp);
1328 cmp = mycmp;
1329
1330 verify();
1331 for (i = 0; i < 10000; i++) {
1332 j = randomnumber(&seed);
1333 j %= NSTR;
1334 printf("trial: %d\n", i);
1335 if (in[j]) {
1336 printf("deleting %s (%d)\n", strings[j], j);
1337 deltest(strings[j]);
1338 in[j] = 0;
1339 } else {
1340 printf("adding %s (%d)\n", strings[j], j);
1341 addtest(strings[j]);
1342 in[j] = 1;
1343 }
d2371c81 1344 findtest();
2d56b16f 1345 }
1346
1347 while (arraylen > 0) {
1348 j = randomnumber(&seed);
1349 j %= arraylen;
1350 deltest(array[j]);
1351 }
1352
d2371c81 1353 freetree234(tree);
1354
1355 /*
1356 * Now try an unsorted tree. We don't really need to test
1357 * delpos234 because we know del234 is based on it, so it's
1358 * already been tested in the above sorted-tree code; but for
1359 * completeness we'll use it to tear down our unsorted tree
1360 * once we've built it.
1361 */
1362 tree = newtree234(NULL);
1363 cmp = NULL;
1364 verify();
1365 for (i = 0; i < 1000; i++) {
1366 printf("trial: %d\n", i);
1367 j = randomnumber(&seed);
1368 j %= NSTR;
1369 k = randomnumber(&seed);
1370 k %= count234(tree)+1;
1371 printf("adding string %s at index %d\n", strings[j], k);
1372 addpostest(strings[j], k);
1373 }
1374 while (count234(tree) > 0) {
1375 printf("cleanup: tree size %d\n", count234(tree));
1376 j = randomnumber(&seed);
1377 j %= count234(tree);
1378 printf("deleting string %s from index %d\n", array[j], j);
1379 delpostest(j);
1380 }
1381
2d56b16f 1382 return 0;
febd9a0f 1383}
2d56b16f 1384
febd9a0f 1385#endif