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