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 ***********************************************************************/
26 ** obj: what to look for
27 ** type: type of search
29 ** Written by Kiem-Phong Vo (05/25/96)
32 /* resize the hash table */
34 static void dthtab(Dt_t
* dt
)
36 static void dthtab(dt
)
40 reg Dtlink_t
*t
, *r
, *p
, **s
, **hs
, **is
, **olds
;
43 if(dt
->data
->minp
> 0 && dt
->data
->ntab
> 0) /* fixed table size */
48 if(dt
->disc
&& dt
->disc
->eventf
&&
49 (*dt
->disc
->eventf
)(dt
, DT_HASHSIZE
, &n
, dt
->disc
) > 0 )
50 { if(n
< 0) /* fix table size */
52 if(dt
->data
->ntab
> 0 )
55 else /* set a particular size */
56 { for(k
= 2; k
< n
; k
*= 2)
63 /* compute new table size */
65 { if((n
= dt
->data
->ntab
) == 0)
67 while(dt
->data
->size
> HLOAD(n
))
70 if(n
== dt
->data
->ntab
)
73 /* allocate new table */
74 olds
= dt
->data
->ntab
== 0 ? NIL(Dtlink_t
**) : dt
->data
->htab
;
75 if(!(s
= (Dtlink_t
**)(*dt
->memoryf
)(dt
,olds
,n
*sizeof(Dtlink_t
*),dt
->disc
)) )
77 olds
= s
+ dt
->data
->ntab
;
82 for(hs
= s
+n
-1; hs
>= olds
; --hs
)
84 for(hs
= s
; hs
< olds
; ++hs
)
85 { for(p
= NIL(Dtlink_t
*), t
= *hs
; t
; t
= r
)
87 if((is
= s
+ HINDEX(n
,t
->hash
)) == hs
)
89 else /* move to a new chain */
93 t
->right
= *is
; *is
= t
;
100 static Void_t
* dthash(Dt_t
* dt
, reg Void_t
* obj
, int type
)
102 static Void_t
* dthash(dt
,obj
,type
)
108 reg Dtlink_t
*t
, *r
, *p
;
114 reg Dtlink_t
**s
, **ends
;
118 /* initialize discipline data */
119 disc
= dt
->disc
; _DTDSC(disc
,ky
,sz
,lk
,cmpf
);
120 dt
->type
&= ~DT_FOUND
;
123 { if(type
&(DT_NEXT
|DT_PREV
))
126 if(dt
->data
->size
<= 0 || !(type
&(DT_CLEAR
|DT_FIRST
|DT_LAST
)) )
129 ends
= (s
= dt
->data
->htab
) + dt
->data
->ntab
;
131 { /* clean out all objects */
135 if(!disc
->freef
&& disc
->link
>= 0)
140 (*disc
->freef
)(dt
,_DTOBJ(t
,lk
),disc
);
142 (*dt
->memoryf
)(dt
,(Void_t
*)t
,0,disc
);
146 dt
->data
->here
= NIL(Dtlink_t
*);
151 else /* computing the first/last object */
152 { t
= NIL(Dtlink_t
*);
153 while(s
< ends
&& !t
)
154 t
= (type
&DT_LAST
) ? *--ends
: *s
++;
155 if(t
&& (type
&DT_LAST
))
156 for(; t
->right
; t
= t
->right
)
161 return t
? _DTOBJ(t
,lk
) : NIL(Void_t
*);
165 /* allow apps to delete an object "actually" in the dictionary */
166 if(dt
->meth
->type
== DT_BAG
&& (type
&(DT_DELETE
|DT_DETACH
)) )
167 { if(!dtsearch(dt
,obj
) )
170 s
= dt
->data
->htab
+ HINDEX(dt
->data
->ntab
,dt
->data
->here
->hash
);
172 for(p
= NIL(Dtlink_t
*), t
= *s
; t
; p
= t
, t
= t
->right
)
173 { if(_DTOBJ(t
,lk
) == obj
) /* delete this specific object */
175 if(t
== dt
->data
->here
)
179 /* delete some matching object */
180 p
= r
; t
= dt
->data
->here
;
184 if(type
&(DT_MATCH
|DT_SEARCH
|DT_INSERT
|DT_ATTACH
) )
185 { key
= (type
&DT_MATCH
) ? obj
: _DTKEY(obj
,ky
,sz
);
186 hsh
= _DTHSH(dt
,key
,disc
,sz
);
189 else if(type
&(DT_RENEW
|DT_VSEARCH
) )
190 { r
= (Dtlink_t
*)obj
;
192 key
= _DTKEY(obj
,ky
,sz
);
196 else /*if(type&(DT_DELETE|DT_DETACH|DT_NEXT|DT_PREV))*/
197 { if((t
= dt
->data
->here
) && _DTOBJ(t
,lk
) == obj
)
199 s
= dt
->data
->htab
+ HINDEX(dt
->data
->ntab
,hsh
);
203 { key
= _DTKEY(obj
,ky
,sz
);
204 hsh
= _DTHSH(dt
,key
,disc
,sz
);
206 t
= dt
->data
->ntab
<= 0 ? NIL(Dtlink_t
*) :
207 *(s
= dt
->data
->htab
+ HINDEX(dt
->data
->ntab
,hsh
));
208 for(p
= NIL(Dtlink_t
*); t
; p
= t
, t
= t
->right
)
210 { k
= _DTOBJ(t
,lk
); k
= _DTKEY(k
,ky
,sz
);
211 if(_DTCMP(dt
,key
,k
,disc
,cmpf
,sz
) == 0)
218 if(t
) /* found matching object */
219 dt
->type
|= DT_FOUND
;
221 if(type
&(DT_MATCH
|DT_SEARCH
|DT_VSEARCH
))
224 if(p
&& (dt
->data
->type
&DT_SET
) && dt
->data
->loop
<= 0)
225 { /* move-to-front heuristic */
233 else if(type
&(DT_INSERT
|DT_ATTACH
))
234 { if(t
&& (dt
->data
->type
&DT_SET
) )
235 { dt
->data
->here
= t
;
239 if(disc
->makef
&& (type
&DT_INSERT
) &&
240 !(obj
= (*disc
->makef
)(dt
,obj
,disc
)) )
245 { r
= (Dtlink_t
*)(*dt
->memoryf
)
246 (dt
,NIL(Void_t
*),sizeof(Dthold_t
),disc
);
248 ((Dthold_t
*)r
)->obj
= obj
;
250 { if(disc
->makef
&& disc
->freef
&& (type
&DT_INSERT
))
251 (*disc
->freef
)(dt
,obj
,disc
);
259 if((dt
->data
->size
+= 1) > HLOAD(dt
->data
->ntab
) && dt
->data
->loop
<= 0 )
261 if(dt
->data
->ntab
== 0)
262 { dt
->data
->size
-= 1;
263 if(disc
->freef
&& (type
&DT_INSERT
))
264 (*disc
->freef
)(dt
,obj
,disc
);
266 (*disc
->memoryf
)(dt
,(Void_t
*)r
,0,disc
);
269 s
= dt
->data
->htab
+ HINDEX(dt
->data
->ntab
,hsh
);
271 { r
->right
= t
->right
;
281 else if(type
&DT_NEXT
)
282 { if(t
&& !(p
= t
->right
) )
283 { for(ends
= dt
->data
->htab
+dt
->data
->ntab
, s
+= 1; s
< ends
; ++s
)
289 else if(type
&DT_PREV
)
292 { while(p
->right
!= t
)
296 { p
= NIL(Dtlink_t
*);
297 for(s
-= 1, ends
= dt
->data
->htab
; s
>= ends
; --s
)
307 if(!(dt
->data
->here
= p
) )
309 if((dt
->data
->loop
-= 1) < 0)
311 if(dt
->data
->size
> HLOAD(dt
->data
->ntab
) && dt
->data
->loop
<= 0)
316 { dt
->data
->type
|= DT_WALK
;
320 else if(type
&DT_RENEW
)
321 { if(!t
|| (dt
->data
->type
&DT_BAG
) )
325 (*disc
->freef
)(dt
,obj
,disc
);
327 (*dt
->memoryf
)(dt
,(Void_t
*)r
,0,disc
);
328 return t
? _DTOBJ(t
,lk
) : NIL(Void_t
*);
331 else /*if(type&(DT_DELETE|DT_DETACH))*/
332 { /* take an element out of the dictionary */
338 else if((p
= *s
) == t
)
341 { while(p
->right
!= t
)
348 if(disc
->freef
&& (type
&DT_DELETE
))
349 (*disc
->freef
)(dt
,obj
,disc
);
351 (*dt
->memoryf
)(dt
,(Void_t
*)t
,0,disc
);
356 static Dtmethod_t _Dtset
= { dthash
, DT_SET
};
357 static Dtmethod_t _Dtbag
= { dthash
, DT_BAG
};
358 __DEFINE__(Dtmethod_t
*,Dtset
,&_Dtset
);
359 __DEFINE__(Dtmethod_t
*,Dtbag
,&_Dtbag
);
361 #ifndef KPVDEL /* for backward compatibility - remove next time */
362 Dtmethod_t _Dthash
= { dthash
, DT_SET
};
363 __DEFINE__(Dtmethod_t
*,Dthash
,&_Dthash
);