1*4887Schin /*********************************************************************** 2*4887Schin * * 3*4887Schin * This software is part of the ast package * 4*4887Schin * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5*4887Schin * and is licensed under the * 6*4887Schin * Common Public License, Version 1.0 * 7*4887Schin * by AT&T Knowledge Ventures * 8*4887Schin * * 9*4887Schin * A copy of the License is available at * 10*4887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 11*4887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*4887Schin * * 13*4887Schin * Information and Software Systems Research * 14*4887Schin * AT&T Research * 15*4887Schin * Florham Park NJ * 16*4887Schin * * 17*4887Schin * Glenn Fowler <gsf@research.att.com> * 18*4887Schin * David Korn <dgk@research.att.com> * 19*4887Schin * Phong Vo <kpv@research.att.com> * 20*4887Schin * * 21*4887Schin ***********************************************************************/ 22*4887Schin #include "dthdr.h" 23*4887Schin 24*4887Schin /* Ordered set/multiset 25*4887Schin ** dt: dictionary being searched 26*4887Schin ** obj: the object to look for. 27*4887Schin ** type: search type. 28*4887Schin ** 29*4887Schin ** Written by Kiem-Phong Vo (5/25/96) 30*4887Schin */ 31*4887Schin 32*4887Schin #if __STD_C 33*4887Schin static Void_t* dttree(Dt_t* dt, Void_t* obj, int type) 34*4887Schin #else 35*4887Schin static Void_t* dttree(dt,obj,type) 36*4887Schin Dt_t* dt; 37*4887Schin Void_t* obj; 38*4887Schin int type; 39*4887Schin #endif 40*4887Schin { 41*4887Schin Dtlink_t *root, *t; 42*4887Schin int cmp, lk, sz, ky; 43*4887Schin Void_t *o, *k, *key; 44*4887Schin Dtlink_t *l, *r, *me, link; 45*4887Schin int n, minp, turn[DT_MINP]; 46*4887Schin Dtcompar_f cmpf; 47*4887Schin Dtdisc_t* disc; 48*4887Schin 49*4887Schin UNFLATTEN(dt); 50*4887Schin disc = dt->disc; _DTDSC(disc,ky,sz,lk,cmpf); 51*4887Schin dt->type &= ~DT_FOUND; 52*4887Schin 53*4887Schin root = dt->data->here; 54*4887Schin if(!obj) 55*4887Schin { if(!root || !(type&(DT_CLEAR|DT_FIRST|DT_LAST)) ) 56*4887Schin return NIL(Void_t*); 57*4887Schin 58*4887Schin if(type&DT_CLEAR) /* delete all objects */ 59*4887Schin { if(disc->freef || disc->link < 0) 60*4887Schin { do 61*4887Schin { while((t = root->left) ) 62*4887Schin RROTATE(root,t); 63*4887Schin t = root->right; 64*4887Schin if(disc->freef) 65*4887Schin (*disc->freef)(dt,_DTOBJ(root,lk),disc); 66*4887Schin if(disc->link < 0) 67*4887Schin (*dt->memoryf)(dt,(Void_t*)root,0,disc); 68*4887Schin } while((root = t) ); 69*4887Schin } 70*4887Schin 71*4887Schin dt->data->size = 0; 72*4887Schin dt->data->here = NIL(Dtlink_t*); 73*4887Schin return NIL(Void_t*); 74*4887Schin } 75*4887Schin else /* computing largest/smallest element */ 76*4887Schin { if(type&DT_LAST) 77*4887Schin { while((t = root->right) ) 78*4887Schin LROTATE(root,t); 79*4887Schin } 80*4887Schin else /* type&DT_FIRST */ 81*4887Schin { while((t = root->left) ) 82*4887Schin RROTATE(root,t); 83*4887Schin } 84*4887Schin 85*4887Schin dt->data->here = root; 86*4887Schin return _DTOBJ(root,lk); 87*4887Schin } 88*4887Schin } 89*4887Schin 90*4887Schin /* note that link.right is LEFT tree and link.left is RIGHT tree */ 91*4887Schin l = r = &link; 92*4887Schin 93*4887Schin /* allow apps to delete an object "actually" in the dictionary */ 94*4887Schin if(dt->meth->type == DT_OBAG && (type&(DT_DELETE|DT_DETACH)) ) 95*4887Schin { key = _DTKEY(obj,ky,sz); 96*4887Schin for(o = dtsearch(dt,obj); o; o = dtnext(dt,o) ) 97*4887Schin { k = _DTKEY(o,ky,sz); 98*4887Schin if(_DTCMP(dt,key,k,disc,cmpf,sz) != 0) 99*4887Schin break; 100*4887Schin if(o == obj) 101*4887Schin { root = dt->data->here; 102*4887Schin l->right = root->left; 103*4887Schin r->left = root->right; 104*4887Schin goto dt_delete; 105*4887Schin } 106*4887Schin } 107*4887Schin } 108*4887Schin 109*4887Schin if(type&(DT_MATCH|DT_SEARCH|DT_INSERT|DT_ATTACH)) 110*4887Schin { key = (type&DT_MATCH) ? obj : _DTKEY(obj,ky,sz); 111*4887Schin if(root) 112*4887Schin goto do_search; 113*4887Schin } 114*4887Schin else if(type&DT_RENEW) 115*4887Schin { me = (Dtlink_t*)obj; 116*4887Schin obj = _DTOBJ(me,lk); 117*4887Schin key = _DTKEY(obj,ky,sz); 118*4887Schin if(root) 119*4887Schin goto do_search; 120*4887Schin } 121*4887Schin else if(root && _DTOBJ(root,lk) != obj) 122*4887Schin { key = _DTKEY(obj,ky,sz); 123*4887Schin do_search: 124*4887Schin if(dt->meth->type == DT_OSET && 125*4887Schin (minp = dt->data->minp) != 0 && (type&(DT_MATCH|DT_SEARCH)) ) 126*4887Schin { /* simple search, note that minp should be even */ 127*4887Schin for(t = root, n = 0; n < minp; ++n) 128*4887Schin { k = _DTOBJ(t,lk); k = _DTKEY(k,ky,sz); 129*4887Schin if((cmp = _DTCMP(dt,key,k,disc,cmpf,sz)) == 0) 130*4887Schin return _DTOBJ(t,lk); 131*4887Schin else 132*4887Schin { turn[n] = cmp; 133*4887Schin if(!(t = cmp < 0 ? t->left : t->right) ) 134*4887Schin return NIL(Void_t*); 135*4887Schin } 136*4887Schin } 137*4887Schin 138*4887Schin /* exceed search length, top-down splay now */ 139*4887Schin for(n = 0; n < minp; n += 2) 140*4887Schin { if(turn[n] < 0) 141*4887Schin { t = root->left; 142*4887Schin if(turn[n+1] < 0) 143*4887Schin { rrotate(root,t); 144*4887Schin rlink(r,t); 145*4887Schin root = t->left; 146*4887Schin } 147*4887Schin else 148*4887Schin { llink(l,t); 149*4887Schin rlink(r,root); 150*4887Schin root = t->right; 151*4887Schin } 152*4887Schin } 153*4887Schin else 154*4887Schin { t = root->right; 155*4887Schin if(turn[n+1] > 0) 156*4887Schin { lrotate(root,t); 157*4887Schin llink(l,t); 158*4887Schin root = t->right; 159*4887Schin } 160*4887Schin else 161*4887Schin { rlink(r,t); 162*4887Schin llink(l,root); 163*4887Schin root = t->left; 164*4887Schin } 165*4887Schin } 166*4887Schin } 167*4887Schin } 168*4887Schin 169*4887Schin while(1) 170*4887Schin { k = _DTOBJ(root,lk); k = _DTKEY(k,ky,sz); 171*4887Schin if((cmp = _DTCMP(dt,key,k,disc,cmpf,sz)) == 0) 172*4887Schin break; 173*4887Schin else if(cmp < 0) 174*4887Schin { if((t = root->left) ) 175*4887Schin { k = _DTOBJ(t,lk); k = _DTKEY(k,ky,sz); 176*4887Schin if((cmp = _DTCMP(dt,key,k,disc,cmpf,sz)) < 0) 177*4887Schin { rrotate(root,t); 178*4887Schin rlink(r,t); 179*4887Schin if(!(root = t->left) ) 180*4887Schin break; 181*4887Schin } 182*4887Schin else if(cmp == 0) 183*4887Schin { rlink(r,root); 184*4887Schin root = t; 185*4887Schin break; 186*4887Schin } 187*4887Schin else /* if(cmp > 0) */ 188*4887Schin { llink(l,t); 189*4887Schin rlink(r,root); 190*4887Schin if(!(root = t->right) ) 191*4887Schin break; 192*4887Schin } 193*4887Schin } 194*4887Schin else 195*4887Schin { rlink(r,root); 196*4887Schin root = NIL(Dtlink_t*); 197*4887Schin break; 198*4887Schin } 199*4887Schin } 200*4887Schin else /* if(cmp > 0) */ 201*4887Schin { if((t = root->right) ) 202*4887Schin { k = _DTOBJ(t,lk); k = _DTKEY(k,ky,sz); 203*4887Schin if((cmp = _DTCMP(dt,key,k,disc,cmpf,sz)) > 0) 204*4887Schin { lrotate(root,t); 205*4887Schin llink(l,t); 206*4887Schin if(!(root = t->right) ) 207*4887Schin break; 208*4887Schin } 209*4887Schin else if(cmp == 0) 210*4887Schin { llink(l,root); 211*4887Schin root = t; 212*4887Schin break; 213*4887Schin } 214*4887Schin else /* if(cmp < 0) */ 215*4887Schin { rlink(r,t); 216*4887Schin llink(l,root); 217*4887Schin if(!(root = t->left) ) 218*4887Schin break; 219*4887Schin } 220*4887Schin } 221*4887Schin else 222*4887Schin { llink(l,root); 223*4887Schin root = NIL(Dtlink_t*); 224*4887Schin break; 225*4887Schin } 226*4887Schin } 227*4887Schin } 228*4887Schin } 229*4887Schin 230*4887Schin if(root) 231*4887Schin { /* found it, now isolate it */ 232*4887Schin dt->type |= DT_FOUND; 233*4887Schin l->right = root->left; 234*4887Schin r->left = root->right; 235*4887Schin 236*4887Schin if(type&(DT_SEARCH|DT_MATCH)) 237*4887Schin { has_root: 238*4887Schin root->left = link.right; 239*4887Schin root->right = link.left; 240*4887Schin if((dt->meth->type&DT_OBAG) && (type&(DT_SEARCH|DT_MATCH)) ) 241*4887Schin { key = _DTOBJ(root,lk); key = _DTKEY(key,ky,sz); 242*4887Schin while((t = root->left) ) 243*4887Schin { /* find max of left subtree */ 244*4887Schin while((r = t->right) ) 245*4887Schin LROTATE(t,r); 246*4887Schin root->left = t; 247*4887Schin 248*4887Schin /* now see if it's in the same group */ 249*4887Schin k = _DTOBJ(t,lk); k = _DTKEY(k,ky,sz); 250*4887Schin if(_DTCMP(dt,key,k,disc,cmpf,sz) != 0) 251*4887Schin break; 252*4887Schin RROTATE(root,t); 253*4887Schin } 254*4887Schin } 255*4887Schin dt->data->here = root; 256*4887Schin return _DTOBJ(root,lk); 257*4887Schin } 258*4887Schin else if(type&DT_NEXT) 259*4887Schin { root->left = link.right; 260*4887Schin root->right = NIL(Dtlink_t*); 261*4887Schin link.right = root; 262*4887Schin dt_next: 263*4887Schin if((root = link.left) ) 264*4887Schin { while((t = root->left) ) 265*4887Schin RROTATE(root,t); 266*4887Schin link.left = root->right; 267*4887Schin goto has_root; 268*4887Schin } 269*4887Schin else goto no_root; 270*4887Schin } 271*4887Schin else if(type&DT_PREV) 272*4887Schin { root->right = link.left; 273*4887Schin root->left = NIL(Dtlink_t*); 274*4887Schin link.left = root; 275*4887Schin dt_prev: 276*4887Schin if((root = link.right) ) 277*4887Schin { while((t = root->right) ) 278*4887Schin LROTATE(root,t); 279*4887Schin link.right = root->left; 280*4887Schin goto has_root; 281*4887Schin } 282*4887Schin else goto no_root; 283*4887Schin } 284*4887Schin else if(type&(DT_DELETE|DT_DETACH)) 285*4887Schin { /* taking an object out of the dictionary */ 286*4887Schin dt_delete: 287*4887Schin obj = _DTOBJ(root,lk); 288*4887Schin if(disc->freef && (type&DT_DELETE)) 289*4887Schin (*disc->freef)(dt,obj,disc); 290*4887Schin if(disc->link < 0) 291*4887Schin (*dt->memoryf)(dt,(Void_t*)root,0,disc); 292*4887Schin if((dt->data->size -= 1) < 0) 293*4887Schin dt->data->size = -1; 294*4887Schin goto no_root; 295*4887Schin } 296*4887Schin else if(type&(DT_INSERT|DT_ATTACH)) 297*4887Schin { if(dt->meth->type&DT_OSET) 298*4887Schin goto has_root; 299*4887Schin else 300*4887Schin { root->left = NIL(Dtlink_t*); 301*4887Schin root->right = link.left; 302*4887Schin link.left = root; 303*4887Schin goto dt_insert; 304*4887Schin } 305*4887Schin } 306*4887Schin else if(type&DT_RENEW) /* a duplicate */ 307*4887Schin { if(dt->meth->type&DT_OSET) 308*4887Schin { if(disc->freef) 309*4887Schin (*disc->freef)(dt,obj,disc); 310*4887Schin if(disc->link < 0) 311*4887Schin (*dt->memoryf)(dt,(Void_t*)me,0,disc); 312*4887Schin } 313*4887Schin else 314*4887Schin { me->left = NIL(Dtlink_t*); 315*4887Schin me->right = link.left; 316*4887Schin link.left = me; 317*4887Schin dt->data->size += 1; 318*4887Schin } 319*4887Schin goto has_root; 320*4887Schin } 321*4887Schin } 322*4887Schin else 323*4887Schin { /* not found, finish up LEFT and RIGHT trees */ 324*4887Schin r->left = NIL(Dtlink_t*); 325*4887Schin l->right = NIL(Dtlink_t*); 326*4887Schin 327*4887Schin if(type&DT_NEXT) 328*4887Schin goto dt_next; 329*4887Schin else if(type&DT_PREV) 330*4887Schin goto dt_prev; 331*4887Schin else if(type&(DT_SEARCH|DT_MATCH)) 332*4887Schin { no_root: 333*4887Schin while((t = r->left) ) 334*4887Schin r = t; 335*4887Schin r->left = link.right; 336*4887Schin dt->data->here = link.left; 337*4887Schin return (type&DT_DELETE) ? obj : NIL(Void_t*); 338*4887Schin } 339*4887Schin else if(type&(DT_INSERT|DT_ATTACH)) 340*4887Schin { dt_insert: 341*4887Schin if(disc->makef && (type&DT_INSERT)) 342*4887Schin obj = (*disc->makef)(dt,obj,disc); 343*4887Schin if(obj) 344*4887Schin { if(lk >= 0) 345*4887Schin root = _DTLNK(obj,lk); 346*4887Schin else 347*4887Schin { root = (Dtlink_t*)(*dt->memoryf) 348*4887Schin (dt,NIL(Void_t*),sizeof(Dthold_t),disc); 349*4887Schin if(root) 350*4887Schin ((Dthold_t*)root)->obj = obj; 351*4887Schin else if(disc->makef && disc->freef && 352*4887Schin (type&DT_INSERT)) 353*4887Schin (*disc->freef)(dt,obj,disc); 354*4887Schin } 355*4887Schin } 356*4887Schin if(root) 357*4887Schin { if(dt->data->size >= 0) 358*4887Schin dt->data->size += 1; 359*4887Schin goto has_root; 360*4887Schin } 361*4887Schin else goto no_root; 362*4887Schin } 363*4887Schin else if(type&DT_RENEW) 364*4887Schin { root = me; 365*4887Schin dt->data->size += 1; 366*4887Schin goto has_root; 367*4887Schin } 368*4887Schin else /*if(type&DT_DELETE)*/ 369*4887Schin { obj = NIL(Void_t*); 370*4887Schin goto no_root; 371*4887Schin } 372*4887Schin } 373*4887Schin 374*4887Schin return NIL(Void_t*); 375*4887Schin } 376*4887Schin 377*4887Schin /* make this method available */ 378*4887Schin static Dtmethod_t _Dtoset = { dttree, DT_OSET }; 379*4887Schin static Dtmethod_t _Dtobag = { dttree, DT_OBAG }; 380*4887Schin __DEFINE__(Dtmethod_t*,Dtoset,&_Dtoset); 381*4887Schin __DEFINE__(Dtmethod_t*,Dtobag,&_Dtobag); 382*4887Schin 383*4887Schin #ifndef KPVDEL /* backward compatibility - delete next time around */ 384*4887Schin Dtmethod_t _Dttree = { dttree, DT_OSET }; 385*4887Schin __DEFINE__(Dtmethod_t*,Dtorder,&_Dttree); 386*4887Schin __DEFINE__(Dtmethod_t*,Dttree,&_Dttree); 387*4887Schin #endif 388*4887Schin 389*4887Schin #ifdef NoF 390*4887Schin NoF(dttree) 391*4887Schin #endif 392