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