tree234.c

Go to the documentation of this file.
00001 /*
00002  * $Id: tree234.c 84 2005-07-01 14:52:38Z bogdan_iancu $
00003  *
00004  * tree234.c: reasonably generic counted 2-3-4 tree routines.
00005  * 
00006  * This file is copyright 1999-2001 Simon Tatham.
00007  * 
00008  * Permission is hereby granted, free of charge, to any person
00009  * obtaining a copy of this software and associated documentation
00010  * files (the "Software"), to deal in the Software without
00011  * restriction, including without limitation the rights to use,
00012  * copy, modify, merge, publish, distribute, sublicense, and/or
00013  * sell copies of the Software, and to permit persons to whom the
00014  * Software is furnished to do so, subject to the following
00015  * conditions:
00016  * 
00017  * The above copyright notice and this permission notice shall be
00018  * included in all copies or substantial portions of the Software.
00019  * 
00020  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00021  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
00022  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00023  * NONINFRINGEMENT.  IN NO EVENT SHALL SIMON TATHAM BE LIABLE FOR
00024  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
00025  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00026  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00027  * SOFTWARE.
00028  *
00029  */
00030 
00031 
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <assert.h>
00035 
00036 #include "tree234.h"
00037 #include "../../mem/shm_mem.h"
00038 
00039 //#define smalloc malloc
00040 //#define sfree free
00041 #define smalloc shm_malloc
00042 #define sfree  shm_free
00043 
00044 #define mknew(typ) ( (typ *) smalloc (sizeof (typ)) )
00045 
00046 #ifdef TEST
00047 #define LOG123(x) (printf x)
00048 #else
00049 #define LOG123(x)
00050 #endif
00051 
00052 typedef struct node234_Tag node234;
00053 
00054 struct tree234_Tag {
00055     node234 *root;
00056     cmpfn234 cmp;
00057 };
00058 
00059 struct node234_Tag {
00060     node234 *parent;
00061     node234 *kids[4];
00062     int counts[4];
00063     void *elems[3];
00064 };
00065 
00066 /*
00067  * Create a 2-3-4 tree.
00068  */
00069 tree234 *newtree234(cmpfn234 cmp) {
00070     tree234 *ret = mknew(tree234);
00071     LOG123(("created tree %p\n", ret));
00072     ret->root = NULL;
00073     ret->cmp = cmp;
00074     return ret;
00075 }
00076 
00077 /*
00078  * Free a 2-3-4 tree (not including freeing the elements).
00079  */
00080 static void freenode234(node234 *n) {
00081     if (!n)
00082    return;
00083     freenode234(n->kids[0]);
00084     freenode234(n->kids[1]);
00085     freenode234(n->kids[2]);
00086     freenode234(n->kids[3]);
00087     sfree(n);
00088 }
00089 void freetree234(tree234 *t)
00090 {
00091     if(t == NULL)
00092       return;
00093     freenode234(t->root);
00094     sfree(t);
00095 }
00096 
00097 /*
00098  * Free a 2-3-4 tree (including freeing the elements with 'fn' function).
00099  */
00100 static void free2node234(node234 *n, freefn fn )
00101 {
00102     if (!n)
00103    return;
00104     free2node234(n->kids[0], fn);
00105     free2node234(n->kids[1], fn);
00106     free2node234(n->kids[2], fn);
00107     free2node234(n->kids[3], fn);
00108     fn(n->elems[0]);
00109     fn(n->elems[1]);
00110     fn(n->elems[2]);
00111     sfree(n);
00112 }
00113 void free2tree234(tree234 *t, freefn fn)
00114 {
00115     if(t == NULL)
00116       return;
00117     free2node234(t->root, fn);
00118     sfree(t);
00119 }
00120 
00121 
00122 /*
00123  * Internal function to count a node.
00124  */
00125 static int countnode234(node234 *n) {
00126     int count = 0;
00127     int i;
00128     if (!n)
00129    return 0;
00130     for (i = 0; i < 4; i++)
00131    count += n->counts[i];
00132     for (i = 0; i < 3; i++)
00133    if (n->elems[i])
00134        count++;
00135     return count;
00136 }
00137 
00138 /*
00139  * Count the elements in a tree.
00140  */
00141 int count234(tree234 *t) {
00142     if (t->root)
00143    return countnode234(t->root);
00144     else
00145    return 0;
00146 }
00147 
00148 /*
00149  * Add an element e to a 2-3-4 tree t. Returns e on success, or if
00150  * an existing element compares equal, returns that.
00151  */
00152 static void *add234_internal(tree234 *t, void *e, int index) {
00153     node234 *n, **np, *left, *right;
00154     void *orig_e = e;
00155     int c, lcount, rcount;
00156 
00157     LOG123(("adding node %p to tree %p\n", e, t));
00158     if (t->root == NULL) {
00159    t->root = mknew(node234);
00160    t->root->elems[1] = t->root->elems[2] = NULL;
00161    t->root->kids[0] = t->root->kids[1] = NULL;
00162    t->root->kids[2] = t->root->kids[3] = NULL;
00163    t->root->counts[0] = t->root->counts[1] = 0;
00164    t->root->counts[2] = t->root->counts[3] = 0;
00165    t->root->parent = NULL;
00166    t->root->elems[0] = e;
00167    LOG123(("  created root %p\n", t->root));
00168    return orig_e;
00169    }
00170 
00171    np = &t->root;
00172    n = *np;
00173 
00174    while (*np) {
00175    int childnum;
00176    n = *np;
00177    LOG123(("  node %p: %p/%d [%p] %p/%d [%p] %p/%d [%p] %p/%d\n",
00178         n,
00179         n->kids[0], n->counts[0], n->elems[0],
00180         n->kids[1], n->counts[1], n->elems[1],
00181         n->kids[2], n->counts[2], n->elems[2],
00182         n->kids[3], n->counts[3]));
00183    if (index >= 0) {
00184        if (!n->kids[0]) {
00185       /*
00186        * Leaf node. We want to insert at kid position
00187        * equal to the index:
00188        * 
00189        *   0 A 1 B 2 C 3
00190        */
00191       childnum = index;
00192        } else {
00193       /*
00194        * Internal node. We always descend through it (add
00195        * always starts at the bottom, never in the
00196        * middle).
00197        */
00198       do { /* this is a do ... while (0) to allow `break' */
00199           if (index <= n->counts[0]) {
00200          childnum = 0;
00201          break;
00202           }
00203           index -= n->counts[0] + 1;
00204           if (index <= n->counts[1]) {
00205          childnum = 1;
00206          break;
00207           }
00208           index -= n->counts[1] + 1;
00209           if (index <= n->counts[2]) {
00210          childnum = 2;
00211          break;
00212           }
00213           index -= n->counts[2] + 1;
00214           if (index <= n->counts[3]) {
00215          childnum = 3;
00216          break;
00217           }
00218           return NULL;       /* error: index out of range */
00219       } while (0);
00220        }
00221    } else {
00222        if ((c = t->cmp(e, n->elems[0])) < 0)
00223       childnum = 0;
00224        else if (c == 0)
00225       return n->elems[0];         /* already exists */
00226        else if (n->elems[1] == NULL || (c = t->cmp(e, n->elems[1])) < 0)
00227       childnum = 1;
00228        else if (c == 0)
00229       return n->elems[1];         /* already exists */
00230        else if (n->elems[2] == NULL || (c = t->cmp(e, n->elems[2])) < 0)
00231       childnum = 2;
00232        else if (c == 0)
00233       return n->elems[2];         /* already exists */
00234        else
00235       childnum = 3;
00236    }
00237    np = &n->kids[childnum];
00238    LOG123(("  moving to child %d (%p)\n", childnum, *np));
00239     }
00240 
00241     /*
00242      * We need to insert the new element in n at position np.
00243      */
00244     left = NULL;  lcount = 0;
00245     right = NULL; rcount = 0;
00246     while (n) {
00247    LOG123(("  at %p: %p/%d [%p] %p/%d [%p] %p/%d [%p] %p/%d\n",
00248         n,
00249         n->kids[0], n->counts[0], n->elems[0],
00250         n->kids[1], n->counts[1], n->elems[1],
00251         n->kids[2], n->counts[2], n->elems[2],
00252         n->kids[3], n->counts[3]));
00253    LOG123(("  need to insert %p/%d [%p] %p/%d at position %d\n",
00254         left, lcount, e, right, rcount, np - n->kids));
00255    if (n->elems[1] == NULL) {
00256        /*
00257         * Insert in a 2-node; simple.
00258         */
00259        if (np == &n->kids[0]) {
00260       LOG123(("  inserting on left of 2-node\n"));
00261       n->kids[2] = n->kids[1];     n->counts[2] = n->counts[1];
00262       n->elems[1] = n->elems[0];
00263       n->kids[1] = right;          n->counts[1] = rcount;
00264       n->elems[0] = e;
00265       n->kids[0] = left;           n->counts[0] = lcount;
00266        } else { /* np == &n->kids[1] */
00267       LOG123(("  inserting on right of 2-node\n"));
00268       n->kids[2] = right;          n->counts[2] = rcount;
00269       n->elems[1] = e;
00270       n->kids[1] = left;           n->counts[1] = lcount;
00271        }
00272        if (n->kids[0]) n->kids[0]->parent = n;
00273        if (n->kids[1]) n->kids[1]->parent = n;
00274        if (n->kids[2]) n->kids[2]->parent = n;
00275        LOG123(("  done\n"));
00276        break;
00277    } else if (n->elems[2] == NULL) {
00278        /*
00279         * Insert in a 3-node; simple.
00280         */
00281        if (np == &n->kids[0]) {
00282       LOG123(("  inserting on left of 3-node\n"));
00283       n->kids[3] = n->kids[2];    n->counts[3] = n->counts[2];
00284       n->elems[2] = n->elems[1];
00285       n->kids[2] = n->kids[1];    n->counts[2] = n->counts[1];
00286       n->elems[1] = n->elems[0];
00287       n->kids[1] = right;         n->counts[1] = rcount;
00288       n->elems[0] = e;
00289       n->kids[0] = left;          n->counts[0] = lcount;
00290        } else if (np == &n->kids[1]) {
00291       LOG123(("  inserting in middle of 3-node\n"));
00292       n->kids[3] = n->kids[2];    n->counts[3] = n->counts[2];
00293       n->elems[2] = n->elems[1];
00294       n->kids[2] = right;         n->counts[2] = rcount;
00295       n->elems[1] = e;
00296       n->kids[1] = left;          n->counts[1] = lcount;
00297        } else { /* np == &n->kids[2] */
00298       LOG123(("  inserting on right of 3-node\n"));
00299       n->kids[3] = right;         n->counts[3] = rcount;
00300       n->elems[2] = e;
00301       n->kids[2] = left;          n->counts[2] = lcount;
00302        }
00303        if (n->kids[0]) n->kids[0]->parent = n;
00304        if (n->kids[1]) n->kids[1]->parent = n;
00305        if (n->kids[2]) n->kids[2]->parent = n;
00306        if (n->kids[3]) n->kids[3]->parent = n;
00307        LOG123(("  done\n"));
00308        break;
00309    } else {
00310        node234 *m = mknew(node234);
00311        m->parent = n->parent;
00312        LOG123(("  splitting a 4-node; created new node %p\n", m));
00313        /*
00314         * Insert in a 4-node; split into a 2-node and a
00315         * 3-node, and move focus up a level.
00316         * 
00317         * I don't think it matters which way round we put the
00318         * 2 and the 3. For simplicity, we'll put the 3 first
00319         * always.
00320         */
00321        if (np == &n->kids[0]) {
00322       m->kids[0] = left;          m->counts[0] = lcount;
00323       m->elems[0] = e;
00324       m->kids[1] = right;         m->counts[1] = rcount;
00325       m->elems[1] = n->elems[0];
00326       m->kids[2] = n->kids[1];    m->counts[2] = n->counts[1];
00327       e = n->elems[1];
00328       n->kids[0] = n->kids[2];    n->counts[0] = n->counts[2];
00329       n->elems[0] = n->elems[2];
00330       n->kids[1] = n->kids[3];    n->counts[1] = n->counts[3];
00331        } else if (np == &n->kids[1]) {
00332       m->kids[0] = n->kids[0];    m->counts[0] = n->counts[0];
00333       m->elems[0] = n->elems[0];
00334       m->kids[1] = left;          m->counts[1] = lcount;
00335       m->elems[1] = e;
00336       m->kids[2] = right;         m->counts[2] = rcount;
00337       e = n->elems[1];
00338       n->kids[0] = n->kids[2];    n->counts[0] = n->counts[2];
00339       n->elems[0] = n->elems[2];
00340       n->kids[1] = n->kids[3];    n->counts[1] = n->counts[3];
00341        } else if (np == &n->kids[2]) {
00342       m->kids[0] = n->kids[0];    m->counts[0] = n->counts[0];
00343       m->elems[0] = n->elems[0];
00344       m->kids[1] = n->kids[1];    m->counts[1] = n->counts[1];
00345       m->elems[1] = n->elems[1];
00346       m->kids[2] = left;          m->counts[2] = lcount;
00347       /* e = e; */
00348       n->kids[0] = right;         n->counts[0] = rcount;
00349       n->elems[0] = n->elems[2];
00350       n->kids[1] = n->kids[3];    n->counts[1] = n->counts[3];
00351        } else { /* np == &n->kids[3] */
00352       m->kids[0] = n->kids[0];    m->counts[0] = n->counts[0];
00353       m->elems[0] = n->elems[0];
00354       m->kids[1] = n->kids[1];    m->counts[1] = n->counts[1];
00355       m->elems[1] = n->elems[1];
00356       m->kids[2] = n->kids[2];    m->counts[2] = n->counts[2];
00357       n->kids[0] = left;          n->counts[0] = lcount;
00358       n->elems[0] = e;
00359       n->kids[1] = right;         n->counts[1] = rcount;
00360       e = n->elems[2];
00361        }
00362        m->kids[3] = n->kids[3] = n->kids[2] = NULL;
00363        m->counts[3] = n->counts[3] = n->counts[2] = 0;
00364        m->elems[2] = n->elems[2] = n->elems[1] = NULL;
00365        if (m->kids[0]) m->kids[0]->parent = m;
00366        if (m->kids[1]) m->kids[1]->parent = m;
00367        if (m->kids[2]) m->kids[2]->parent = m;
00368        if (n->kids[0]) n->kids[0]->parent = n;
00369        if (n->kids[1]) n->kids[1]->parent = n;
00370        LOG123(("  left (%p): %p/%d [%p] %p/%d [%p] %p/%d\n", m,
00371        m->kids[0], m->counts[0], m->elems[0],
00372        m->kids[1], m->counts[1], m->elems[1],
00373        m->kids[2], m->counts[2]));
00374        LOG123(("  right (%p): %p/%d [%p] %p/%d\n", n,
00375        n->kids[0], n->counts[0], n->elems[0],
00376        n->kids[1], n->counts[1]));
00377        left = m;  lcount = countnode234(left);
00378        right = n; rcount = countnode234(right);
00379    }
00380    if (n->parent)
00381        np = (n->parent->kids[0] == n ? &n->parent->kids[0] :
00382         n->parent->kids[1] == n ? &n->parent->kids[1] :
00383         n->parent->kids[2] == n ? &n->parent->kids[2] :
00384         &n->parent->kids[3]);
00385    n = n->parent;
00386     }
00387 
00388     /*
00389      * If we've come out of here by `break', n will still be
00390      * non-NULL and all we need to do is go back up the tree
00391      * updating counts. If we've come here because n is NULL, we
00392      * need to create a new root for the tree because the old one
00393      * has just split into two. */
00394     if (n) {
00395    while (n->parent) {
00396        int count = countnode234(n);
00397        int childnum;
00398        childnum = (n->parent->kids[0] == n ? 0 :
00399          n->parent->kids[1] == n ? 1 :
00400          n->parent->kids[2] == n ? 2 : 3);
00401        n->parent->counts[childnum] = count;
00402        n = n->parent;
00403    }
00404     } else {
00405    LOG123(("  root is overloaded, split into two\n"));
00406    t->root = mknew(node234);
00407    t->root->kids[0] = left;     t->root->counts[0] = lcount;
00408    t->root->elems[0] = e;
00409    t->root->kids[1] = right;    t->root->counts[1] = rcount;
00410    t->root->elems[1] = NULL;
00411    t->root->kids[2] = NULL;     t->root->counts[2] = 0;
00412    t->root->elems[2] = NULL;
00413    t->root->kids[3] = NULL;     t->root->counts[3] = 0;
00414    t->root->parent = NULL;
00415    if (t->root->kids[0]) t->root->kids[0]->parent = t->root;
00416    if (t->root->kids[1]) t->root->kids[1]->parent = t->root;
00417    LOG123(("  new root is %p/%d [%p] %p/%d\n",
00418         t->root->kids[0], t->root->counts[0],
00419         t->root->elems[0],
00420         t->root->kids[1], t->root->counts[1]));
00421     }
00422 
00423     return orig_e;
00424 }
00425 
00426 void *add234(tree234 *t, void *e) {
00427     if (!t->cmp)            /* tree is unsorted */
00428    return NULL;
00429 
00430     return add234_internal(t, e, -1);
00431 }
00432 void *addpos234(tree234 *t, void *e, int index) {
00433     if (index < 0 ||           /* index out of range */
00434    t->cmp)               /* tree is sorted */
00435    return NULL;             /* return failure */
00436 
00437     return add234_internal(t, e, index);  /* this checks the upper bound */
00438 }
00439 
00440 /*
00441  * Look up the element at a given numeric index in a 2-3-4 tree.
00442  * Returns NULL if the index is out of range.
00443  */
00444 void *index234(tree234 *t, int index) {
00445     node234 *n;
00446 
00447     if (!t->root)
00448    return NULL;             /* tree is empty */
00449 
00450     if (index < 0 || index >= countnode234(t->root))
00451    return NULL;             /* out of range */
00452 
00453     n = t->root;
00454     
00455     while (n) {
00456    if (index < n->counts[0])
00457        n = n->kids[0];
00458    else if (index -= n->counts[0] + 1, index < 0)
00459        return n->elems[0];
00460    else if (index < n->counts[1])
00461        n = n->kids[1];
00462    else if (index -= n->counts[1] + 1, index < 0)
00463        return n->elems[1];
00464    else if (index < n->counts[2])
00465        n = n->kids[2];
00466    else if (index -= n->counts[2] + 1, index < 0)
00467        return n->elems[2];
00468    else
00469        n = n->kids[3];
00470     }
00471 
00472     /* We shouldn't ever get here. I wonder how we did. */
00473     return NULL;
00474 }
00475 
00476 /*
00477  * Find an element e in a sorted 2-3-4 tree t. Returns NULL if not
00478  * found. e is always passed as the first argument to cmp, so cmp
00479  * can be an asymmetric function if desired. cmp can also be passed
00480  * as NULL, in which case the compare function from the tree proper
00481  * will be used.
00482  */
00483 void *findrelpos234(tree234 *t, void *e, cmpfn234 cmp,
00484           int relation, int *index) {
00485     node234 *n;
00486     void *ret;
00487     int c;
00488     int idx, ecount, kcount, cmpret;
00489 
00490     if (t->root == NULL)
00491    return NULL;
00492 
00493     if (cmp == NULL)
00494    cmp = t->cmp;
00495 
00496     n = t->root;
00497     /*
00498      * Attempt to find the element itself.
00499      */
00500     idx = 0;
00501     ecount = -1;
00502     /*
00503      * Prepare a fake `cmp' result if e is NULL.
00504      */
00505     cmpret = 0;
00506     if (e == NULL) {
00507    assert(relation == REL234_LT || relation == REL234_GT);
00508    if (relation == REL234_LT)
00509        cmpret = +1;         /* e is a max: always greater */
00510    else if (relation == REL234_GT)
00511        cmpret = -1;         /* e is a min: always smaller */
00512     }
00513     while (1) {
00514    for (kcount = 0; kcount < 4; kcount++) {
00515        if (kcount >= 3 || n->elems[kcount] == NULL ||
00516       (c = cmpret ? cmpret : cmp(e, n->elems[kcount])) < 0) {
00517       break;
00518        }
00519        if (n->kids[kcount]) idx += n->counts[kcount];
00520        if (c == 0) {
00521       ecount = kcount;
00522       break;
00523        }
00524        idx++;
00525    }
00526    if (ecount >= 0)
00527        break;
00528    if (n->kids[kcount])
00529        n = n->kids[kcount];
00530    else
00531        break;
00532     }
00533 
00534     if (ecount >= 0) {
00535    /*
00536     * We have found the element we're looking for. It's
00537     * n->elems[ecount], at tree index idx. If our search
00538     * relation is EQ, LE or GE we can now go home.
00539     */
00540    if (relation != REL234_LT && relation != REL234_GT) {
00541        if (index) *index = idx;
00542        return n->elems[ecount];
00543    }
00544 
00545    /*
00546     * Otherwise, we'll do an indexed lookup for the previous
00547     * or next element. (It would be perfectly possible to
00548     * implement these search types in a non-counted tree by
00549     * going back up from where we are, but far more fiddly.)
00550     */
00551    if (relation == REL234_LT)
00552        idx--;
00553    else
00554        idx++;
00555     } else {
00556    /*
00557     * We've found our way to the bottom of the tree and we
00558     * know where we would insert this node if we wanted to:
00559     * we'd put it in in place of the (empty) subtree
00560     * n->kids[kcount], and it would have index idx
00561     * 
00562     * But the actual element isn't there. So if our search
00563     * relation is EQ, we're doomed.
00564     */
00565    if (relation == REL234_EQ)
00566        return NULL;
00567 
00568    /*
00569     * Otherwise, we must do an index lookup for index idx-1
00570     * (if we're going left - LE or LT) or index idx (if we're
00571     * going right - GE or GT).
00572     */
00573    if (relation == REL234_LT || relation == REL234_LE) {
00574        idx--;
00575    }
00576     }
00577 
00578     /*
00579      * We know the index of the element we want; just call index234
00580      * to do the rest. This will return NULL if the index is out of
00581      * bounds, which is exactly what we want.
00582      */
00583     ret = index234(t, idx);
00584     if (ret && index) *index = idx;
00585     return ret;
00586 }
00587 void *find234(tree234 *t, void *e, cmpfn234 cmp) {
00588     return findrelpos234(t, e, cmp, REL234_EQ, NULL);
00589 }
00590 void *findrel234(tree234 *t, void *e, cmpfn234 cmp, int relation) {
00591     return findrelpos234(t, e, cmp, relation, NULL);
00592 }
00593 void *findpos234(tree234 *t, void *e, cmpfn234 cmp, int *index) {
00594     return findrelpos234(t, e, cmp, REL234_EQ, index);
00595 }
00596 
00597 /*
00598  * Delete an element e in a 2-3-4 tree. Does not free the element,
00599  * merely removes all links to it from the tree nodes.
00600  */
00601 static void *delpos234_internal(tree234 *t, int index) {
00602     node234 *n;
00603     void *retval;
00604     int ei = -1;
00605 
00606     retval = 0;
00607 
00608     n = t->root;
00609     LOG123(("deleting item %d from tree %p\n", index, t));
00610     while (1) {
00611    while (n) {
00612        int ki;
00613        node234 *sub;
00614 
00615        LOG123(("  node %p: %p/%d [%p] %p/%d [%p] %p/%d [%p] %p/%d index=%d\n",
00616        n,
00617        n->kids[0], n->counts[0], n->elems[0],
00618        n->kids[1], n->counts[1], n->elems[1],
00619        n->kids[2], n->counts[2], n->elems[2],
00620        n->kids[3], n->counts[3],
00621        index));
00622        if (index < n->counts[0]) {
00623       ki = 0;
00624        } else if (index -= n->counts[0]+1, index < 0) {
00625       ei = 0; break;
00626        } else if (index < n->counts[1]) {
00627       ki = 1;
00628        } else if (index -= n->counts[1]+1, index < 0) {
00629       ei = 1; break;
00630        } else if (index < n->counts[2]) {
00631       ki = 2;
00632        } else if (index -= n->counts[2]+1, index < 0) {
00633       ei = 2; break;
00634        } else {
00635       ki = 3;
00636        }
00637        /*
00638         * Recurse down to subtree ki. If it has only one element,
00639         * we have to do some transformation to start with.
00640         */
00641        LOG123(("  moving to subtree %d\n", ki));
00642        sub = n->kids[ki];
00643        if (!sub->elems[1]) {
00644       LOG123(("  subtree has only one element!\n", ki));
00645       if (ki > 0 && n->kids[ki-1]->elems[1]) {
00646           /*
00647            * Case 3a, left-handed variant. Child ki has
00648            * only one element, but child ki-1 has two or
00649            * more. So we need to move a subtree from ki-1
00650            * to ki.
00651            * 
00652            *                . C .                     . B .
00653            *               /     \     ->            /     \
00654            * [more] a A b B c   d D e      [more] a A b   c C d D e
00655            */
00656           node234 *sib = n->kids[ki-1];
00657           int lastelem = (sib->elems[2] ? 2 :
00658                 sib->elems[1] ? 1 : 0);
00659           sub->kids[2] = sub->kids[1];
00660           sub->counts[2] = sub->counts[1];
00661           sub->elems[1] = sub->elems[0];
00662           sub->kids[1] = sub->kids[0];
00663           sub->counts[1] = sub->counts[0];
00664           sub->elems[0] = n->elems[ki-1];
00665           sub->kids[0] = sib->kids[lastelem+1];
00666           sub->counts[0] = sib->counts[lastelem+1];
00667           if (sub->kids[0]) sub->kids[0]->parent = sub;
00668           n->elems[ki-1] = sib->elems[lastelem];
00669           sib->kids[lastelem+1] = NULL;
00670           sib->counts[lastelem+1] = 0;
00671           sib->elems[lastelem] = NULL;
00672           n->counts[ki] = countnode234(sub);
00673           LOG123(("  case 3a left\n"));
00674           LOG123(("  index and left subtree count before adjustment: %d, %d\n",
00675           index, n->counts[ki-1]));
00676           index += n->counts[ki-1];
00677           n->counts[ki-1] = countnode234(sib);
00678           index -= n->counts[ki-1];
00679           LOG123(("  index and left subtree count after adjustment: %d, %d\n",
00680           index, n->counts[ki-1]));
00681       } else if (ki < 3 && n->kids[ki+1] &&
00682             n->kids[ki+1]->elems[1]) {
00683           /*
00684            * Case 3a, right-handed variant. ki has only
00685            * one element but ki+1 has two or more. Move a
00686            * subtree from ki+1 to ki.
00687            * 
00688            *      . B .                             . C .
00689            *     /     \                ->         /     \
00690            *  a A b   c C d D e [more]      a A b B c   d D e [more]
00691            */
00692           node234 *sib = n->kids[ki+1];
00693           int j;
00694           sub->elems[1] = n->elems[ki];
00695           sub->kids[2] = sib->kids[0];
00696           sub->counts[2] = sib->counts[0];
00697           if (sub->kids[2]) sub->kids[2]->parent = sub;
00698           n->elems[ki] = sib->elems[0];
00699           sib->kids[0] = sib->kids[1];
00700           sib->counts[0] = sib->counts[1];
00701           for (j = 0; j < 2 && sib->elems[j+1]; j++) {
00702          sib->kids[j+1] = sib->kids[j+2];
00703          sib->counts[j+1] = sib->counts[j+2];
00704          sib->elems[j] = sib->elems[j+1];
00705           }
00706           sib->kids[j+1] = NULL;
00707           sib->counts[j+1] = 0;
00708           sib->elems[j] = NULL;
00709           n->counts[ki] = countnode234(sub);
00710           n->counts[ki+1] = countnode234(sib);
00711           LOG123(("  case 3a right\n"));
00712       } else {
00713           /*
00714            * Case 3b. ki has only one element, and has no
00715            * neighbor with more than one. So pick a
00716            * neighbor and merge it with ki, taking an
00717            * element down from n to go in the middle.
00718            *
00719            *      . B .                .
00720            *     /     \     ->        |
00721            *  a A b   c C d      a A b B c C d
00722            * 
00723            * (Since at all points we have avoided
00724            * descending to a node with only one element,
00725            * we can be sure that n is not reduced to
00726            * nothingness by this move, _unless_ it was
00727            * the very first node, ie the root of the
00728            * tree. In that case we remove the now-empty
00729            * root and replace it with its single large
00730            * child as shown.)
00731            */
00732           node234 *sib;
00733           int j;
00734 
00735           if (ki > 0) {
00736          ki--;
00737          index += n->counts[ki] + 1;
00738           }
00739           sib = n->kids[ki];
00740           sub = n->kids[ki+1];
00741 
00742           sub->kids[3] = sub->kids[1];
00743           sub->counts[3] = sub->counts[1];
00744           sub->elems[2] = sub->elems[0];
00745           sub->kids[2] = sub->kids[0];
00746           sub->counts[2] = sub->counts[0];
00747           sub->elems[1] = n->elems[ki];
00748           sub->kids[1] = sib->kids[1];
00749           sub->counts[1] = sib->counts[1];
00750           if (sub->kids[1]) sub->kids[1]->parent = sub;
00751           sub->elems[0] = sib->elems[0];
00752           sub->kids[0] = sib->kids[0];
00753           sub->counts[0] = sib->counts[0];
00754           if (sub->kids[0]) sub->kids[0]->parent = sub;
00755 
00756           n->counts[ki+1] = countnode234(sub);
00757 
00758           sfree(sib);
00759 
00760           /*
00761            * That's built the big node in sub. Now we
00762            * need to remove the reference to sib in n.
00763            */
00764           for (j = ki; j < 3 && n->kids[j+1]; j++) {
00765          n->kids[j] = n->kids[j+1];
00766          n->counts[j] = n->counts[j+1];
00767          n->elems[j] = j<2 ? n->elems[j+1] : NULL;
00768           }
00769           n->kids[j] = NULL;
00770           n->counts[j] = 0;
00771           if (j < 3) n->elems[j] = NULL;
00772           LOG123(("  case 3b ki=%d\n", ki));
00773 
00774           if (!n->elems[0]) {
00775          /*
00776           * The root is empty and needs to be
00777           * removed.
00778           */
00779          LOG123(("  shifting root!\n"));
00780          t->root = sub;
00781          sub->parent = NULL;
00782          sfree(n);
00783           }
00784       }
00785        }
00786        n = sub;
00787    }
00788    if (!retval)
00789        retval = n->elems[ei];
00790 
00791    if (ei==-1)
00792        return NULL;         /* although this shouldn't happen */
00793 
00794    /*
00795     * Treat special case: this is the one remaining item in
00796     * the tree. n is the tree root (no parent), has one
00797     * element (no elems[1]), and has no kids (no kids[0]).
00798     */
00799    if (!n->parent && !n->elems[1] && !n->kids[0]) {
00800        LOG123(("  removed last element in tree\n"));
00801        sfree(n);
00802        t->root = NULL;
00803        return retval;
00804    }
00805 
00806    /*
00807     * Now we have the element we want, as n->elems[ei], and we
00808     * have also arranged for that element not to be the only
00809     * one in its node. So...
00810     */
00811 
00812    if (!n->kids[0] && n->elems[1]) {
00813        /*
00814         * Case 1. n is a leaf node with more than one element,
00815         * so it's _really easy_. Just delete the thing and
00816         * we're done.
00817         */
00818        int i;
00819        LOG123(("  case 1\n"));
00820        for (i = ei; i < 2 && n->elems[i+1]; i++)
00821       n->elems[i] = n->elems[i+1];
00822        n->elems[i] = NULL;
00823        /*
00824         * Having done that to the leaf node, we now go back up
00825         * the tree fixing the counts.
00826         */
00827        while (n->parent) {
00828       int childnum;
00829       childnum = (n->parent->kids[0] == n ? 0 :
00830              n->parent->kids[1] == n ? 1 :
00831              n->parent->kids[2] == n ? 2 : 3);
00832       n->parent->counts[childnum]--;
00833       n = n->parent;
00834        }
00835        return retval;          /* finished! */
00836    } else if (n->kids[ei]->elems[1]) {
00837        /*
00838         * Case 2a. n is an internal node, and the root of the
00839         * subtree to the left of e has more than one element.
00840         * So find the predecessor p to e (ie the largest node
00841         * in that subtree), place it where e currently is, and
00842         * then start the deletion process over again on the
00843         * subtree with p as target.
00844         */
00845        node234 *m = n->kids[ei];
00846        void *target;
00847        LOG123(("  case 2a\n"));
00848        while (m->kids[0]) {
00849       m = (m->kids[3] ? m->kids[3] :
00850            m->kids[2] ? m->kids[2] :
00851            m->kids[1] ? m->kids[1] : m->kids[0]);          
00852        }
00853        target = (m->elems[2] ? m->elems[2] :
00854             m->elems[1] ? m->elems[1] : m->elems[0]);
00855        n->elems[ei] = target;
00856        index = n->counts[ei]-1;
00857        n = n->kids[ei];
00858    } else if (n->kids[ei+1]->elems[1]) {
00859        /*
00860         * Case 2b, symmetric to 2a but s/left/right/ and
00861         * s/predecessor/successor/. (And s/largest/smallest/).
00862         */
00863        node234 *m = n->kids[ei+1];
00864        void *target;
00865        LOG123(("  case 2b\n"));
00866        while (m->kids[0]) {
00867       m = m->kids[0];
00868        }
00869        target = m->elems[0];
00870        n->elems[ei] = target;
00871        n = n->kids[ei+1];
00872        index = 0;
00873    } else {
00874        /*
00875         * Case 2c. n is an internal node, and the subtrees to
00876         * the left and right of e both have only one element.
00877         * So combine the two subnodes into a single big node
00878         * with their own elements on the left and right and e
00879         * in the middle, then restart the deletion process on
00880         * that subtree, with e still as target.
00881         */
00882        node234 *a = n->kids[ei], *b = n->kids[ei+1];
00883        int j;
00884 
00885        LOG123(("  case 2c\n"));
00886        a->elems[1] = n->elems[ei];
00887        a->kids[2] = b->kids[0];
00888        a->counts[2] = b->counts[0];
00889        if (a->kids[2]) a->kids[2]->parent = a;
00890        a->elems[2] = b->elems[0];
00891        a->kids[3] = b->kids[1];
00892        a->counts[3] = b->counts[1];
00893        if (a->kids[3]) a->kids[3]->parent = a;
00894        sfree(b);
00895        n->counts[ei] = countnode234(a);
00896        /*
00897         * That's built the big node in a, and destroyed b. Now
00898         * remove the reference to b (and e) in n.
00899         */
00900        for (j = ei; j < 2 && n->elems[j+1]; j++) {
00901       n->elems[j] = n->elems[j+1];
00902       n->kids[j+1] = n->kids[j+2];
00903       n->counts[j+1] = n->counts[j+2];
00904        }
00905        n->elems[j] = NULL;
00906        n->kids[j+1] = NULL;
00907        n->counts[j+1] = 0;
00908             /*
00909              * It's possible, in this case, that we've just removed
00910              * the only element in the root of the tree. If so,
00911              * shift the root.
00912              */
00913             if (n->elems[0] == NULL) {
00914                 LOG123(("  shifting root!\n"));
00915                 t->root = a;
00916                 a->parent = NULL;
00917                 sfree(n);
00918             }
00919        /*
00920         * Now go round the deletion process again, with n
00921         * pointing at the new big node and e still the same.
00922         */
00923        n = a;
00924        index = a->counts[0] + a->counts[1] + 1;
00925    }
00926     }
00927 }
00928 void *delpos234(tree234 *t, int index) {
00929     if (index < 0 || index >= countnode234(t->root))
00930    return NULL;
00931     return delpos234_internal(t, index);
00932 }
00933 void *del234(tree234 *t, void *e) {
00934     int index;
00935     if (!findrelpos234(t, e, NULL, REL234_EQ, &index))
00936       return NULL;             /* it wasn't in there anyway */
00937     return delpos234_internal(t, index); /* it's there; delete it. */
00938 }
00939 
00940 #ifdef TEST
00941 
00942 /*
00943  * Test code for the 2-3-4 tree. This code maintains an alternative
00944  * representation of the data in the tree, in an array (using the
00945  * obvious and slow insert and delete functions). After each tree
00946  * operation, the verify() function is called, which ensures all
00947  * the tree properties are preserved:
00948  *  - node->child->parent always equals node
00949  *  - tree->root->parent always equals NULL
00950  *  - number of kids == 0 or number of elements + 1;
00951  *  - tree has the same depth everywhere
00952  *  - every node has at least one element
00953  *  - subtree element counts are accurate
00954  *  - any NULL kid pointer is accompanied by a zero count
00955  *  - in a sorted tree: ordering property between elements of a
00956  *    node and elements of its children is preserved
00957  * and also ensures the list represented by the tree is the same
00958  * list it should be. (This last check also doubly verifies the
00959  * ordering properties, because the `same list it should be' is by
00960  * definition correctly ordered. It also ensures all nodes are
00961  * distinct, because the enum functions would get caught in a loop
00962  * if not.)
00963  */
00964 
00965 #include <stdarg.h>
00966 
00967 #define srealloc realloc
00968 
00969 /*
00970  * Error reporting function.
00971  */
00972 void error(char *fmt, ...) {
00973     va_list ap;
00974     printf("ERROR: ");
00975     va_start(ap, fmt);
00976     vfprintf(stdout, fmt, ap);
00977     va_end(ap);
00978     printf("\n");
00979 }
00980 
00981 /* The array representation of the data. */
00982 void **array;
00983 int arraylen, arraysize;
00984 cmpfn234 cmp;
00985 
00986 /* The tree representation of the same data. */
00987 tree234 *tree;
00988 
00989 typedef struct {
00990     int treedepth;
00991     int elemcount;
00992 } chkctx;
00993 
00994 int chknode(chkctx *ctx, int level, node234 *node,
00995              void *lowbound, void *highbound) {
00996     int nkids, nelems;
00997     int i;
00998     int count;
00999 
01000     /* Count the non-NULL kids. */
01001     for (nkids = 0; nkids < 4 && node->kids[nkids]; nkids++);
01002     /* Ensure no kids beyond the first NULL are non-NULL. */
01003     for (i = nkids; i < 4; i++)
01004         if (node->kids[i]) {
01005             error("node %p: nkids=%d but kids[%d] non-NULL",
01006                    node, nkids, i);
01007         } else if (node->counts[i]) {
01008             error("node %p: kids[%d] NULL but count[%d]=%d nonzero",
01009                    node, i, i, node->counts[i]);
01010    }
01011 
01012     /* Count the non-NULL elements. */
01013     for (nelems = 0; nelems < 3 && node->elems[nelems]; nelems++);
01014     /* Ensure no elements beyond the first NULL are non-NULL. */
01015     for (i = nelems; i < 3; i++)
01016         if (node->elems[i]) {
01017             error("node %p: nelems=%d but elems[%d] non-NULL",
01018                    node, nelems, i);
01019         }
01020 
01021     if (nkids == 0) {
01022         /*
01023          * If nkids==0, this is a leaf node; verify that the tree
01024          * depth is the same everywhere.
01025          */
01026         if (ctx->treedepth < 0)
01027             ctx->treedepth = level;    /* we didn't know the depth yet */
01028         else if (ctx->treedepth != level)
01029             error("node %p: leaf at depth %d, previously seen depth %d",
01030                    node, level, ctx->treedepth);
01031     } else {
01032         /*
01033          * If nkids != 0, then it should be nelems+1, unless nelems
01034          * is 0 in which case nkids should also be 0 (and so we
01035          * shouldn't be in this condition at all).
01036          */
01037         int shouldkids = (nelems ? nelems+1 : 0);
01038         if (nkids != shouldkids) {
01039             error("node %p: %d elems should mean %d kids but has %d",
01040                    node, nelems, shouldkids, nkids);
01041         }
01042     }
01043 
01044     /*
01045      * nelems should be at least 1.
01046      */
01047     if (nelems == 0) {
01048         error("node %p: no elems", node, nkids);
01049     }
01050 
01051     /*
01052      * Add nelems to the running element count of the whole tree.
01053      */
01054     ctx->elemcount += nelems;
01055 
01056     /*
01057      * Check ordering property: all elements should be strictly >
01058      * lowbound, strictly < highbound, and strictly < each other in
01059      * sequence. (lowbound and highbound are NULL at edges of tree
01060      * - both NULL at root node - and NULL is considered to be <
01061      * everything and > everything. IYSWIM.)
01062      */
01063     if (cmp) {
01064    for (i = -1; i < nelems; i++) {
01065        void *lower = (i == -1 ? lowbound : node->elems[i]);
01066        void *higher = (i+1 == nelems ? highbound : node->elems[i+1]);
01067        if (lower && higher && cmp(lower, higher) >= 0) {
01068       error("node %p: kid comparison [%d=%s,%d=%s] failed",
01069             node, i, lower, i+1, higher);
01070        }
01071    }
01072     }
01073 
01074     /*
01075      * Check parent pointers: all non-NULL kids should have a
01076      * parent pointer coming back to this node.
01077      */
01078     for (i = 0; i < nkids; i++)
01079         if (node->kids[i]->parent != node) {
01080             error("node %p kid %d: parent ptr is %p not %p",
01081                    node, i, node->kids[i]->parent, node);
01082         }
01083 
01084 
01085     /*
01086      * Now (finally!) recurse into subtrees.
01087      */
01088     count = nelems;
01089 
01090     for (i = 0; i < nkids; i++) {
01091         void *lower = (i == 0 ? lowbound : node->elems[i-1]);
01092         void *higher = (i >= nelems ? highbound : node->elems[i]);
01093    int subcount = chknode(ctx, level+1, node->kids[i], lower, higher);
01094    if (node->counts[i] != subcount) {
01095        error("node %p kid %d: count says %d, subtree really has %d",
01096         node, i, node->counts[i], subcount);
01097    }
01098         count += subcount;
01099     }
01100 
01101     return count;
01102 }
01103 
01104 void verify(void) {
01105     chkctx ctx;
01106     int i;
01107     void *p;
01108 
01109     ctx.treedepth = -1;                /* depth unknown yet */
01110     ctx.elemcount = 0;                 /* no elements seen yet */
01111     /*
01112      * Verify validity of tree properties.
01113      */
01114     if (tree->root) {
01115    if (tree->root->parent != NULL)
01116        error("root->parent is %p should be null", tree->root->parent);
01117         chknode(&ctx, 0, tree->root, NULL, NULL);
01118     }
01119     printf("tree depth: %d\n", ctx.treedepth);
01120     /*
01121      * Enumerate the tree and ensure it matches up to the array.
01122      */
01123     for (i = 0; NULL != (p = index234(tree, i)); i++) {
01124         if (i >= arraylen)
01125             error("tree contains more than %d elements", arraylen);
01126         if (array[i] != p)
01127             error("enum at position %d: array says %s, tree says %s",
01128                    i, array[i], p);
01129     }
01130     if (ctx.elemcount != i) {
01131         error("tree really contains %d elements, enum gave %d",
01132                ctx.elemcount, i);
01133     }
01134     if (i < arraylen) {
01135         error("enum gave only %d elements, array has %d", i, arraylen);
01136     }
01137     i = count234(tree);
01138     if (ctx.elemcount != i) {
01139         error("tree really contains %d elements, count234 gave %d",
01140          ctx.elemcount, i);
01141     }
01142 }
01143 
01144 void internal_addtest(void *elem, int index, void *realret) {
01145     int i, j;
01146     void *retval;
01147 
01148     if (arraysize < arraylen+1) {
01149         arraysize = arraylen+1+256;
01150         array = (array == NULL ? smalloc(arraysize*sizeof(*array)) :
01151                  srealloc(array, arraysize*sizeof(*array)));
01152     }
01153 
01154     i = index;
01155     /* now i points to the first element >= elem */
01156     retval = elem;                  /* expect elem returned (success) */
01157     for (j = arraylen; j > i; j--)
01158    array[j] = array[j-1];
01159     array[i] = elem;                /* add elem to array */
01160     arraylen++;
01161 
01162     if (realret != retval) {
01163         error("add: retval was %p expected %p", realret, retval);
01164     }
01165 
01166     verify();
01167 }
01168 
01169 void addtest(void *elem) {
01170     int i;
01171     void *realret;
01172 
01173     realret = add234(tree, elem);
01174 
01175     i = 0;
01176     while (i < arraylen && cmp(elem, array[i]) > 0)
01177         i++;
01178     if (i < arraylen && !cmp(elem, array[i])) {
01179         void *retval = array[i];       /* expect that returned not elem */
01180    if (realret != retval) {
01181        error("add: retval was %p expected %p", realret, retval);
01182    }
01183     } else
01184    internal_addtest(elem, i, realret);
01185 }
01186 
01187 void addpostest(void *elem, int i) {
01188     void *realret;
01189 
01190     realret = addpos234(tree, elem, i);
01191 
01192     internal_addtest(elem, i, realret);
01193 }
01194 
01195 void delpostest(int i) {
01196     int index = i;
01197     void *elem = array[i], *ret;
01198 
01199     /* i points to the right element */
01200     while (i < arraylen-1) {
01201    array[i] = array[i+1];
01202    i++;
01203     }
01204     arraylen--;                /* delete elem from array */
01205 
01206     if (tree->cmp)
01207    ret = del234(tree, elem);
01208     else
01209    ret = delpos234(tree, index);
01210 
01211     if (ret != elem) {
01212    error("del returned %p, expected %p", ret, elem);
01213     }
01214 
01215     verify();
01216 }
01217 
01218 void deltest(void *elem) {
01219     int i;
01220 
01221     i = 0;
01222     while (i < arraylen && cmp(elem, array[i]) > 0)
01223         i++;
01224     if (i >= arraylen || cmp(elem, array[i]) != 0)
01225         return;                        /* don't do it! */
01226     delpostest(i);
01227 }
01228 
01229 /* A sample data set and test utility. Designed for pseudo-randomness,
01230  * and yet repeatability. */
01231 
01232 /*
01233  * This random number generator uses the `portable implementation'
01234  * given in ANSI C99 draft N869. It assumes `unsigned' is 32 bits;
01235  * change it if not.
01236  */
01237 int randomnumber(unsigned *seed) {
01238     *seed *= 1103515245;
01239     *seed += 12345;
01240     return ((*seed) / 65536) % 32768;
01241 }
01242 
01243 int mycmp(void *av, void *bv) {
01244     char const *a = (char const *)av;
01245     char const *b = (char const *)bv;
01246     return strcmp(a, b);
01247 }
01248 
01249 #define lenof(x) ( sizeof((x)) / sizeof(*(x)) )
01250 
01251 char *strings[] = {
01252     "a", "ab", "absque", "coram", "de",
01253     "palam", "clam", "cum", "ex", "e",
01254     "sine", "tenus", "pro", "prae",
01255     "banana", "carrot", "cabbage", "broccoli", "onion", "zebra",
01256     "penguin", "blancmange", "pangolin", "whale", "hedgehog",
01257     "giraffe", "peanut", "bungee", "foo", "bar", "baz", "quux",
01258     "murfl", "spoo", "breen", "flarn", "octothorpe",
01259     "snail", "tiger", "elephant", "octopus", "warthog", "armadillo",
01260     "aardvark", "wyvern", "dragon", "elf", "dwarf", "orc", "goblin",
01261     "pixie", "basilisk", "warg", "ape", "lizard", "newt", "shopkeeper",
01262     "wand", "ring", "amulet"
01263 };
01264 
01265 #define NSTR lenof(strings)
01266 
01267 int findtest(void) {
01268     const static int rels[] = {
01269    REL234_EQ, REL234_GE, REL234_LE, REL234_LT, REL234_GT
01270     };
01271     const static char *const relnames[] = {
01272    "EQ", "GE", "LE", "LT", "GT"
01273     };
01274     int i, j, rel, index;
01275     char *p, *ret, *realret, *realret2;
01276     int lo, hi, mid, c;
01277 
01278     for (i = 0; i < NSTR; i++) {
01279    p = strings[i];
01280    for (j = 0; j < sizeof(rels)/sizeof(*rels); j++) {
01281        rel = rels[j];
01282 
01283        lo = 0; hi = arraylen-1;
01284        while (lo <= hi) {
01285       mid = (lo + hi) / 2;
01286       c = strcmp(p, array[mid]);
01287       if (c < 0)
01288           hi = mid-1;
01289       else if (c > 0)
01290           lo = mid+1;
01291       else
01292           break;
01293        }
01294 
01295        if (c == 0) {
01296       if (rel == REL234_LT)
01297           ret = (mid > 0 ? array[--mid] : NULL);
01298       else if (rel == REL234_GT)
01299           ret = (mid < arraylen-1 ? array[++mid] : NULL);
01300       else
01301           ret = array[mid];
01302        } else {
01303       assert(lo == hi+1);
01304       if (rel == REL234_LT || rel == REL234_LE) {
01305           mid = hi;
01306           ret = (hi >= 0 ? array[hi] : NULL);
01307       } else if (rel == REL234_GT || rel == REL234_GE) {
01308           mid = lo;
01309           ret = (lo < arraylen ? array[lo] : NULL);
01310       } else
01311           ret = NULL;
01312        }
01313 
01314        realret = findrelpos234(tree, p, NULL, rel, &index);
01315        if (realret != ret) {
01316       error("find(\"%s\",%s) gave %s should be %s",
01317             p, relnames[j], realret, ret);
01318        }
01319        if (realret && index != mid) {
01320       error("find(\"%s\",%s) gave %d should be %d",
01321             p, relnames[j], index, mid);
01322        }
01323        if (realret && rel == REL234_EQ) {
01324       realret2 = index234(tree, index);
01325       if (realret2 != realret) {
01326           error("find(\"%s\",%s) gave %s(%d) but %d -> %s",
01327            p, relnames[j], realret, index, index, realret2);
01328       }
01329        }
01330 #if 0
01331        printf("find(\"%s\",%s) gave %s(%d)\n", p, relnames[j],
01332          realret, index);
01333 #endif
01334    }
01335     }
01336 
01337     realret = findrelpos234(tree, NULL, NULL, REL234_GT, &index);
01338     if (arraylen && (realret != array[0] || index != 0)) {
01339    error("find(NULL,GT) gave %s(%d) should be %s(0)",
01340          realret, index, array[0]);
01341     } else if (!arraylen && (realret != NULL)) {
01342    error("find(NULL,GT) gave %s(%d) should be NULL",
01343          realret, index);
01344     }
01345 
01346     realret = findrelpos234(tree, NULL, NULL, REL234_LT, &index);
01347     if (arraylen && (realret != array[arraylen-1] || index != arraylen-1)) {
01348    error("find(NULL,LT) gave %s(%d) should be %s(0)",
01349          realret, index, array[arraylen-1]);
01350     } else if (!arraylen && (realret != NULL)) {
01351    error("find(NULL,LT) gave %s(%d) should be NULL",
01352          realret, index);
01353     }
01354 }
01355 
01356 int main(void) {
01357     int in[NSTR];
01358     int i, j, k;
01359     unsigned seed = 0;
01360 
01361     for (i = 0; i < NSTR; i++) in[i] = 0;
01362     array = NULL;
01363     arraylen = arraysize = 0;
01364     tree = newtree234(mycmp);
01365     cmp = mycmp;
01366 
01367     verify();
01368     for (i = 0; i < 10000; i++) {
01369         j = randomnumber(&seed);
01370         j %= NSTR;
01371         printf("trial: %d\n", i);
01372         if (in[j]) {
01373             printf("deleting %s (%d)\n", strings[j], j);
01374             deltest(strings[j]);
01375             in[j] = 0;
01376         } else {
01377             printf("adding %s (%d)\n", strings[j], j);
01378             addtest(strings[j]);
01379             in[j] = 1;
01380         }
01381    findtest();
01382     }
01383 
01384     while (arraylen > 0) {
01385         j = randomnumber(&seed);
01386         j %= arraylen;
01387         deltest(array[j]);
01388     }
01389 
01390     freetree234(tree);
01391 
01392     /*
01393      * Now try an unsorted tree. We don't really need to test
01394      * delpos234 because we know del234 is based on it, so it's
01395      * already been tested in the above sorted-tree code; but for
01396      * completeness we'll use it to tear down our unsorted tree
01397      * once we've built it.
01398      */
01399     tree = newtree234(NULL);
01400     cmp = NULL;
01401     verify();
01402     for (i = 0; i < 1000; i++) {
01403    printf("trial: %d\n", i);
01404    j = randomnumber(&seed);
01405    j %= NSTR;
01406    k = randomnumber(&seed);
01407    k %= count234(tree)+1;
01408    printf("adding string %s at index %d\n", strings[j], k);
01409    addpostest(strings[j], k);
01410     }
01411     while (count234(tree) > 0) {
01412    printf("cleanup: tree size %d\n", count234(tree));
01413    j = randomnumber(&seed);
01414    j %= count234(tree);
01415    printf("deleting string %s from index %d\n", array[j], j);
01416    delpostest(j);
01417     }
01418 
01419     return 0;
01420 }
01421 
01422 #endif

Generated on Thu May 24 20:00:33 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6