xref: /onnv-gate/usr/src/lib/libast/common/cdt/dttree.c (revision 12068:08a39a083754)
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