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