14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * Glenn Fowler <gsf@research.att.com> *
184887Schin * David Korn <dgk@research.att.com> *
194887Schin * Phong Vo <kpv@research.att.com> *
204887Schin * *
214887Schin ***********************************************************************/
224887Schin #include "dthdr.h"
234887Schin
244887Schin /* Ordered set/multiset
254887Schin ** dt: dictionary being searched
264887Schin ** obj: the object to look for.
274887Schin ** type: search type.
284887Schin **
294887Schin ** Written by Kiem-Phong Vo (5/25/96)
304887Schin */
314887Schin
324887Schin #if __STD_C
dttree(Dt_t * dt,Void_t * obj,int type)334887Schin static Void_t* dttree(Dt_t* dt, Void_t* obj, int type)
344887Schin #else
354887Schin static Void_t* dttree(dt,obj,type)
364887Schin Dt_t* dt;
374887Schin Void_t* obj;
384887Schin int type;
394887Schin #endif
404887Schin {
414887Schin Dtlink_t *root, *t;
424887Schin int cmp, lk, sz, ky;
434887Schin Void_t *o, *k, *key;
444887Schin Dtlink_t *l, *r, *me, link;
454887Schin int n, minp, turn[DT_MINP];
464887Schin Dtcompar_f cmpf;
474887Schin Dtdisc_t* disc;
484887Schin
494887Schin UNFLATTEN(dt);
504887Schin disc = dt->disc; _DTDSC(disc,ky,sz,lk,cmpf);
514887Schin dt->type &= ~DT_FOUND;
524887Schin
534887Schin root = dt->data->here;
544887Schin if(!obj)
554887Schin { if(!root || !(type&(DT_CLEAR|DT_FIRST|DT_LAST)) )
564887Schin return NIL(Void_t*);
574887Schin
584887Schin if(type&DT_CLEAR) /* delete all objects */
594887Schin { if(disc->freef || disc->link < 0)
604887Schin { do
614887Schin { while((t = root->left) )
624887Schin RROTATE(root,t);
634887Schin t = root->right;
644887Schin if(disc->freef)
654887Schin (*disc->freef)(dt,_DTOBJ(root,lk),disc);
664887Schin if(disc->link < 0)
674887Schin (*dt->memoryf)(dt,(Void_t*)root,0,disc);
684887Schin } while((root = t) );
694887Schin }
704887Schin
714887Schin dt->data->size = 0;
724887Schin dt->data->here = NIL(Dtlink_t*);
734887Schin return NIL(Void_t*);
744887Schin }
754887Schin else /* computing largest/smallest element */
764887Schin { if(type&DT_LAST)
774887Schin { while((t = root->right) )
784887Schin LROTATE(root,t);
794887Schin }
804887Schin else /* type&DT_FIRST */
814887Schin { while((t = root->left) )
824887Schin RROTATE(root,t);
834887Schin }
844887Schin
854887Schin dt->data->here = root;
864887Schin return _DTOBJ(root,lk);
874887Schin }
884887Schin }
894887Schin
904887Schin /* note that link.right is LEFT tree and link.left is RIGHT tree */
914887Schin l = r = &link;
924887Schin
934887Schin /* allow apps to delete an object "actually" in the dictionary */
944887Schin if(dt->meth->type == DT_OBAG && (type&(DT_DELETE|DT_DETACH)) )
954887Schin { key = _DTKEY(obj,ky,sz);
964887Schin for(o = dtsearch(dt,obj); o; o = dtnext(dt,o) )
974887Schin { k = _DTKEY(o,ky,sz);
984887Schin if(_DTCMP(dt,key,k,disc,cmpf,sz) != 0)
994887Schin break;
1004887Schin if(o == obj)
1014887Schin { root = dt->data->here;
1024887Schin l->right = root->left;
1034887Schin r->left = root->right;
1044887Schin goto dt_delete;
1054887Schin }
1064887Schin }
1074887Schin }
1084887Schin
1094887Schin if(type&(DT_MATCH|DT_SEARCH|DT_INSERT|DT_ATTACH))
1104887Schin { key = (type&DT_MATCH) ? obj : _DTKEY(obj,ky,sz);
1114887Schin if(root)
1124887Schin goto do_search;
1134887Schin }
1144887Schin else if(type&DT_RENEW)
1154887Schin { me = (Dtlink_t*)obj;
1164887Schin obj = _DTOBJ(me,lk);
1174887Schin key = _DTKEY(obj,ky,sz);
1184887Schin if(root)
1194887Schin goto do_search;
1204887Schin }
1214887Schin else if(root && _DTOBJ(root,lk) != obj)
1224887Schin { key = _DTKEY(obj,ky,sz);
1234887Schin do_search:
1244887Schin if(dt->meth->type == DT_OSET &&
1254887Schin (minp = dt->data->minp) != 0 && (type&(DT_MATCH|DT_SEARCH)) )
1264887Schin { /* simple search, note that minp should be even */
1274887Schin for(t = root, n = 0; n < minp; ++n)
1284887Schin { k = _DTOBJ(t,lk); k = _DTKEY(k,ky,sz);
1294887Schin if((cmp = _DTCMP(dt,key,k,disc,cmpf,sz)) == 0)
1304887Schin return _DTOBJ(t,lk);
1314887Schin else
1324887Schin { turn[n] = cmp;
1334887Schin if(!(t = cmp < 0 ? t->left : t->right) )
1344887Schin return NIL(Void_t*);
1354887Schin }
1364887Schin }
1374887Schin
1384887Schin /* exceed search length, top-down splay now */
1394887Schin for(n = 0; n < minp; n += 2)
1404887Schin { if(turn[n] < 0)
1414887Schin { t = root->left;
1424887Schin if(turn[n+1] < 0)
1434887Schin { rrotate(root,t);
1444887Schin rlink(r,t);
1454887Schin root = t->left;
1464887Schin }
1474887Schin else
1484887Schin { llink(l,t);
1494887Schin rlink(r,root);
1504887Schin root = t->right;
1514887Schin }
1524887Schin }
1534887Schin else
1544887Schin { t = root->right;
1554887Schin if(turn[n+1] > 0)
1564887Schin { lrotate(root,t);
1574887Schin llink(l,t);
1584887Schin root = t->right;
1594887Schin }
1604887Schin else
1614887Schin { rlink(r,t);
1624887Schin llink(l,root);
1634887Schin root = t->left;
1644887Schin }
1654887Schin }
1664887Schin }
1674887Schin }
1684887Schin
1694887Schin while(1)
1704887Schin { k = _DTOBJ(root,lk); k = _DTKEY(k,ky,sz);
1714887Schin if((cmp = _DTCMP(dt,key,k,disc,cmpf,sz)) == 0)
1724887Schin break;
1734887Schin else if(cmp < 0)
1744887Schin { if((t = root->left) )
1754887Schin { k = _DTOBJ(t,lk); k = _DTKEY(k,ky,sz);
1764887Schin if((cmp = _DTCMP(dt,key,k,disc,cmpf,sz)) < 0)
1774887Schin { rrotate(root,t);
1784887Schin rlink(r,t);
1794887Schin if(!(root = t->left) )
1804887Schin break;
1814887Schin }
1824887Schin else if(cmp == 0)
1834887Schin { rlink(r,root);
1844887Schin root = t;
1854887Schin break;
1864887Schin }
1874887Schin else /* if(cmp > 0) */
1884887Schin { llink(l,t);
1894887Schin rlink(r,root);
1904887Schin if(!(root = t->right) )
1914887Schin break;
1924887Schin }
1934887Schin }
1944887Schin else
1954887Schin { rlink(r,root);
1964887Schin root = NIL(Dtlink_t*);
1974887Schin break;
1984887Schin }
1994887Schin }
2004887Schin else /* if(cmp > 0) */
2014887Schin { if((t = root->right) )
2024887Schin { k = _DTOBJ(t,lk); k = _DTKEY(k,ky,sz);
2034887Schin if((cmp = _DTCMP(dt,key,k,disc,cmpf,sz)) > 0)
2044887Schin { lrotate(root,t);
2054887Schin llink(l,t);
2064887Schin if(!(root = t->right) )
2074887Schin break;
2084887Schin }
2094887Schin else if(cmp == 0)
2104887Schin { llink(l,root);
2114887Schin root = t;
2124887Schin break;
2134887Schin }
2144887Schin else /* if(cmp < 0) */
2154887Schin { rlink(r,t);
2164887Schin llink(l,root);
2174887Schin if(!(root = t->left) )
2184887Schin break;
2194887Schin }
2204887Schin }
2214887Schin else
2224887Schin { llink(l,root);
2234887Schin root = NIL(Dtlink_t*);
2244887Schin break;
2254887Schin }
2264887Schin }
2274887Schin }
2284887Schin }
2294887Schin
2304887Schin if(root)
2314887Schin { /* found it, now isolate it */
2324887Schin dt->type |= DT_FOUND;
2334887Schin l->right = root->left;
2344887Schin r->left = root->right;
2354887Schin
2364887Schin if(type&(DT_SEARCH|DT_MATCH))
2374887Schin { has_root:
2384887Schin root->left = link.right;
2394887Schin root->right = link.left;
2404887Schin if((dt->meth->type&DT_OBAG) && (type&(DT_SEARCH|DT_MATCH)) )
2414887Schin { key = _DTOBJ(root,lk); key = _DTKEY(key,ky,sz);
2424887Schin while((t = root->left) )
2434887Schin { /* find max of left subtree */
2444887Schin while((r = t->right) )
2454887Schin LROTATE(t,r);
2464887Schin root->left = t;
2474887Schin
2484887Schin /* now see if it's in the same group */
2494887Schin k = _DTOBJ(t,lk); k = _DTKEY(k,ky,sz);
2504887Schin if(_DTCMP(dt,key,k,disc,cmpf,sz) != 0)
2514887Schin break;
2524887Schin RROTATE(root,t);
2534887Schin }
2544887Schin }
2554887Schin dt->data->here = root;
2564887Schin return _DTOBJ(root,lk);
2574887Schin }
2584887Schin else if(type&DT_NEXT)
2594887Schin { root->left = link.right;
2604887Schin root->right = NIL(Dtlink_t*);
2614887Schin link.right = root;
2624887Schin dt_next:
2634887Schin if((root = link.left) )
2644887Schin { while((t = root->left) )
2654887Schin RROTATE(root,t);
2664887Schin link.left = root->right;
2674887Schin goto has_root;
2684887Schin }
2694887Schin else goto no_root;
2704887Schin }
2714887Schin else if(type&DT_PREV)
2724887Schin { root->right = link.left;
2734887Schin root->left = NIL(Dtlink_t*);
2744887Schin link.left = root;
2754887Schin dt_prev:
2764887Schin if((root = link.right) )
2774887Schin { while((t = root->right) )
2784887Schin LROTATE(root,t);
2794887Schin link.right = root->left;
2804887Schin goto has_root;
2814887Schin }
2824887Schin else goto no_root;
2834887Schin }
2844887Schin else if(type&(DT_DELETE|DT_DETACH))
2854887Schin { /* taking an object out of the dictionary */
2864887Schin dt_delete:
2874887Schin obj = _DTOBJ(root,lk);
2884887Schin if(disc->freef && (type&DT_DELETE))
2894887Schin (*disc->freef)(dt,obj,disc);
2904887Schin if(disc->link < 0)
2914887Schin (*dt->memoryf)(dt,(Void_t*)root,0,disc);
2924887Schin if((dt->data->size -= 1) < 0)
2934887Schin dt->data->size = -1;
2944887Schin goto no_root;
2954887Schin }
2964887Schin else if(type&(DT_INSERT|DT_ATTACH))
2974887Schin { if(dt->meth->type&DT_OSET)
2984887Schin goto has_root;
2994887Schin else
3004887Schin { root->left = NIL(Dtlink_t*);
3014887Schin root->right = link.left;
3024887Schin link.left = root;
3034887Schin goto dt_insert;
3044887Schin }
3054887Schin }
3064887Schin else if(type&DT_RENEW) /* a duplicate */
3074887Schin { if(dt->meth->type&DT_OSET)
3084887Schin { if(disc->freef)
3094887Schin (*disc->freef)(dt,obj,disc);
3104887Schin if(disc->link < 0)
3114887Schin (*dt->memoryf)(dt,(Void_t*)me,0,disc);
3124887Schin }
3134887Schin else
3144887Schin { me->left = NIL(Dtlink_t*);
3154887Schin me->right = link.left;
3164887Schin link.left = me;
3174887Schin dt->data->size += 1;
3184887Schin }
3194887Schin goto has_root;
3204887Schin }
3214887Schin }
3224887Schin else
3234887Schin { /* not found, finish up LEFT and RIGHT trees */
3244887Schin r->left = NIL(Dtlink_t*);
3254887Schin l->right = NIL(Dtlink_t*);
3264887Schin
3274887Schin if(type&DT_NEXT)
3284887Schin goto dt_next;
3294887Schin else if(type&DT_PREV)
3304887Schin goto dt_prev;
3314887Schin else if(type&(DT_SEARCH|DT_MATCH))
3324887Schin { no_root:
3334887Schin while((t = r->left) )
3344887Schin r = t;
3354887Schin r->left = link.right;
3364887Schin dt->data->here = link.left;
3374887Schin return (type&DT_DELETE) ? obj : NIL(Void_t*);
3384887Schin }
3394887Schin else if(type&(DT_INSERT|DT_ATTACH))
3404887Schin { dt_insert:
3414887Schin if(disc->makef && (type&DT_INSERT))
3424887Schin obj = (*disc->makef)(dt,obj,disc);
3434887Schin if(obj)
3444887Schin { if(lk >= 0)
3454887Schin root = _DTLNK(obj,lk);
3464887Schin else
3474887Schin { root = (Dtlink_t*)(*dt->memoryf)
3484887Schin (dt,NIL(Void_t*),sizeof(Dthold_t),disc);
3494887Schin if(root)
3504887Schin ((Dthold_t*)root)->obj = obj;
3514887Schin else if(disc->makef && disc->freef &&
3524887Schin (type&DT_INSERT))
3534887Schin (*disc->freef)(dt,obj,disc);
3544887Schin }
3554887Schin }
3564887Schin if(root)
3574887Schin { if(dt->data->size >= 0)
3584887Schin dt->data->size += 1;
3594887Schin goto has_root;
3604887Schin }
3614887Schin else goto no_root;
3624887Schin }
3634887Schin else if(type&DT_RENEW)
3644887Schin { root = me;
3654887Schin dt->data->size += 1;
3664887Schin goto has_root;
3674887Schin }
3684887Schin else /*if(type&DT_DELETE)*/
3694887Schin { obj = NIL(Void_t*);
3704887Schin goto no_root;
3714887Schin }
3724887Schin }
3734887Schin
3744887Schin return NIL(Void_t*);
3754887Schin }
3764887Schin
3774887Schin /* make this method available */
3784887Schin static Dtmethod_t _Dtoset = { dttree, DT_OSET };
3794887Schin static Dtmethod_t _Dtobag = { dttree, DT_OBAG };
3804887Schin __DEFINE__(Dtmethod_t*,Dtoset,&_Dtoset);
3814887Schin __DEFINE__(Dtmethod_t*,Dtobag,&_Dtobag);
3824887Schin
3834887Schin #ifndef KPVDEL /* backward compatibility - delete next time around */
3844887Schin Dtmethod_t _Dttree = { dttree, DT_OSET };
3854887Schin __DEFINE__(Dtmethod_t*,Dtorder,&_Dttree);
3864887Schin __DEFINE__(Dtmethod_t*,Dttree,&_Dttree);
3874887Schin #endif
3884887Schin
3894887Schin #ifdef NoF
3904887Schin NoF(dttree)
3914887Schin #endif
392