1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
24 /* Ordered set/multiset
25 ** dt: dictionary being searched
26 ** obj: the object to look for.
29 ** Written by Kiem-Phong Vo (5/25/96)
33 static Void_t
* dttree(Dt_t
* dt
, Void_t
* obj
, int type
)
35 static Void_t
* dttree(dt
,obj
,type
)
44 Dtlink_t
*l
, *r
, *me
, link
;
45 int n
, minp
, turn
[DT_MINP
];
50 disc
= dt
->disc
; _DTDSC(disc
,ky
,sz
,lk
,cmpf
);
51 dt
->type
&= ~DT_FOUND
;
53 root
= dt
->data
->here
;
55 { if(!root
|| !(type
&(DT_CLEAR
|DT_FIRST
|DT_LAST
)) )
58 if(type
&DT_CLEAR
) /* delete all objects */
59 { if(disc
->freef
|| disc
->link
< 0)
61 { while((t
= root
->left
) )
65 (*disc
->freef
)(dt
,_DTOBJ(root
,lk
),disc
);
67 (*dt
->memoryf
)(dt
,(Void_t
*)root
,0,disc
);
72 dt
->data
->here
= NIL(Dtlink_t
*);
75 else /* computing largest/smallest element */
77 { while((t
= root
->right
) )
80 else /* type&DT_FIRST */
81 { while((t
= root
->left
) )
85 dt
->data
->here
= root
;
86 return _DTOBJ(root
,lk
);
90 /* note that link.right is LEFT tree and link.left is RIGHT tree */
93 /* allow apps to delete an object "actually" in the dictionary */
94 if(dt
->meth
->type
== DT_OBAG
&& (type
&(DT_DELETE
|DT_DETACH
)) )
95 { key
= _DTKEY(obj
,ky
,sz
);
96 for(o
= dtsearch(dt
,obj
); o
; o
= dtnext(dt
,o
) )
97 { k
= _DTKEY(o
,ky
,sz
);
98 if(_DTCMP(dt
,key
,k
,disc
,cmpf
,sz
) != 0)
101 { root
= dt
->data
->here
;
102 l
->right
= root
->left
;
103 r
->left
= root
->right
;
109 if(type
&(DT_MATCH
|DT_SEARCH
|DT_INSERT
|DT_ATTACH
))
110 { key
= (type
&DT_MATCH
) ? obj
: _DTKEY(obj
,ky
,sz
);
114 else if(type
&DT_RENEW
)
115 { me
= (Dtlink_t
*)obj
;
117 key
= _DTKEY(obj
,ky
,sz
);
121 else if(root
&& _DTOBJ(root
,lk
) != obj
)
122 { key
= _DTKEY(obj
,ky
,sz
);
124 if(dt
->meth
->type
== DT_OSET
&&
125 (minp
= dt
->data
->minp
) != 0 && (type
&(DT_MATCH
|DT_SEARCH
)) )
126 { /* simple search, note that minp should be even */
127 for(t
= root
, n
= 0; n
< minp
; ++n
)
128 { k
= _DTOBJ(t
,lk
); k
= _DTKEY(k
,ky
,sz
);
129 if((cmp
= _DTCMP(dt
,key
,k
,disc
,cmpf
,sz
)) == 0)
133 if(!(t
= cmp
< 0 ? t
->left
: t
->right
) )
138 /* exceed search length, top-down splay now */
139 for(n
= 0; n
< minp
; n
+= 2)
170 { k
= _DTOBJ(root
,lk
); k
= _DTKEY(k
,ky
,sz
);
171 if((cmp
= _DTCMP(dt
,key
,k
,disc
,cmpf
,sz
)) == 0)
174 { if((t
= root
->left
) )
175 { k
= _DTOBJ(t
,lk
); k
= _DTKEY(k
,ky
,sz
);
176 if((cmp
= _DTCMP(dt
,key
,k
,disc
,cmpf
,sz
)) < 0)
179 if(!(root
= t
->left
) )
187 else /* if(cmp > 0) */
190 if(!(root
= t
->right
) )
196 root
= NIL(Dtlink_t
*);
200 else /* if(cmp > 0) */
201 { if((t
= root
->right
) )
202 { k
= _DTOBJ(t
,lk
); k
= _DTKEY(k
,ky
,sz
);
203 if((cmp
= _DTCMP(dt
,key
,k
,disc
,cmpf
,sz
)) > 0)
206 if(!(root
= t
->right
) )
214 else /* if(cmp < 0) */
217 if(!(root
= t
->left
) )
223 root
= NIL(Dtlink_t
*);
231 { /* found it, now isolate it */
232 dt
->type
|= DT_FOUND
;
233 l
->right
= root
->left
;
234 r
->left
= root
->right
;
236 if(type
&(DT_SEARCH
|DT_MATCH
))
238 root
->left
= link
.right
;
239 root
->right
= link
.left
;
240 if((dt
->meth
->type
&DT_OBAG
) && (type
&(DT_SEARCH
|DT_MATCH
)) )
241 { key
= _DTOBJ(root
,lk
); key
= _DTKEY(key
,ky
,sz
);
242 while((t
= root
->left
) )
243 { /* find max of left subtree */
244 while((r
= t
->right
) )
248 /* now see if it's in the same group */
249 k
= _DTOBJ(t
,lk
); k
= _DTKEY(k
,ky
,sz
);
250 if(_DTCMP(dt
,key
,k
,disc
,cmpf
,sz
) != 0)
255 dt
->data
->here
= root
;
256 return _DTOBJ(root
,lk
);
258 else if(type
&DT_NEXT
)
259 { root
->left
= link
.right
;
260 root
->right
= NIL(Dtlink_t
*);
263 if((root
= link
.left
) )
264 { while((t
= root
->left
) )
266 link
.left
= root
->right
;
271 else if(type
&DT_PREV
)
272 { root
->right
= link
.left
;
273 root
->left
= NIL(Dtlink_t
*);
276 if((root
= link
.right
) )
277 { while((t
= root
->right
) )
279 link
.right
= root
->left
;
284 else if(type
&(DT_DELETE
|DT_DETACH
))
285 { /* taking an object out of the dictionary */
287 obj
= _DTOBJ(root
,lk
);
288 if(disc
->freef
&& (type
&DT_DELETE
))
289 (*disc
->freef
)(dt
,obj
,disc
);
291 (*dt
->memoryf
)(dt
,(Void_t
*)root
,0,disc
);
292 if((dt
->data
->size
-= 1) < 0)
296 else if(type
&(DT_INSERT
|DT_ATTACH
))
297 { if(dt
->meth
->type
&DT_OSET
)
300 { root
->left
= NIL(Dtlink_t
*);
301 root
->right
= link
.left
;
306 else if(type
&DT_RENEW
) /* a duplicate */
307 { if(dt
->meth
->type
&DT_OSET
)
309 (*disc
->freef
)(dt
,obj
,disc
);
311 (*dt
->memoryf
)(dt
,(Void_t
*)me
,0,disc
);
314 { me
->left
= NIL(Dtlink_t
*);
315 me
->right
= link
.left
;
323 { /* not found, finish up LEFT and RIGHT trees */
324 r
->left
= NIL(Dtlink_t
*);
325 l
->right
= NIL(Dtlink_t
*);
329 else if(type
&DT_PREV
)
331 else if(type
&(DT_SEARCH
|DT_MATCH
))
333 while((t
= r
->left
) )
335 r
->left
= link
.right
;
336 dt
->data
->here
= link
.left
;
337 return (type
&DT_DELETE
) ? obj
: NIL(Void_t
*);
339 else if(type
&(DT_INSERT
|DT_ATTACH
))
341 if(disc
->makef
&& (type
&DT_INSERT
))
342 obj
= (*disc
->makef
)(dt
,obj
,disc
);
345 root
= _DTLNK(obj
,lk
);
347 { root
= (Dtlink_t
*)(*dt
->memoryf
)
348 (dt
,NIL(Void_t
*),sizeof(Dthold_t
),disc
);
350 ((Dthold_t
*)root
)->obj
= obj
;
351 else if(disc
->makef
&& disc
->freef
&&
353 (*disc
->freef
)(dt
,obj
,disc
);
357 { if(dt
->data
->size
>= 0)
363 else if(type
&DT_RENEW
)
368 else /*if(type&DT_DELETE)*/
369 { obj
= NIL(Void_t
*);
377 /* make this method available */
378 static Dtmethod_t _Dtoset
= { dttree
, DT_OSET
};
379 static Dtmethod_t _Dtobag
= { dttree
, DT_OBAG
};
380 __DEFINE__(Dtmethod_t
*,Dtoset
,&_Dtoset
);
381 __DEFINE__(Dtmethod_t
*,Dtobag
,&_Dtobag
);
383 #ifndef KPVDEL /* backward compatibility - delete next time around */
384 Dtmethod_t _Dttree
= { dttree
, DT_OSET
};
385 __DEFINE__(Dtmethod_t
*,Dtorder
,&_Dttree
);
386 __DEFINE__(Dtmethod_t
*,Dttree
,&_Dttree
);