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