3 ** hash manager for lua
6 char *rcs_hash
="$Id: hash.c,v 2.30 1996/05/06 14:30:27 roberto Exp $";
16 #define nhash(t) ((t)->nhash)
17 #define nuse(t) ((t)->nuse)
18 #define markarray(t) ((t)->mark)
19 #define nodevector(t) ((t)->node)
20 #define node(t,i) (&(t)->node[i])
21 #define ref(n) (&(n)->ref)
22 #define val(n) (&(n)->val)
25 #define REHASH_LIMIT 0.70 /* avoid more than this % full */
28 static Hash
*listhead
= NULL
;
31 /* hash dimensions values */
32 static Long dimensions
[] =
33 {3L, 5L, 7L, 11L, 23L, 47L, 97L, 197L, 397L, 797L, 1597L, 3203L, 6421L,
34 12853L, 25717L, 51437L, 102811L, 205619L, 411233L, 822433L,
35 1644817L, 3289613L, 6579211L, 13158023L, MAX_INT
};
37 int luaI_redimension (int nhash
)
40 for (i
=0; dimensions
[i
]<MAX_INT
; i
++)
42 if (dimensions
[i
] > nhash
)
45 lua_error("table overflow");
46 return 0; /* to avoid warnings */
49 static int hashindex (Hash
*t
, Object
*ref
) /* hash function */
54 lua_error ("unexpected type to index table");
55 return -1; /* UNREACHEABLE */
57 return (((int)nvalue(ref
))%nhash(t
));
59 return (int)((tsvalue(ref
)->hash
)%nhash(t
)); /* make it a valid index */
61 return (((IntPoint
)ref
->value
.tf
)%nhash(t
));
63 return (((IntPoint
)fvalue(ref
))%nhash(t
));
65 return (((IntPoint
)avalue(ref
))%nhash(t
));
66 default: /* user data */
67 return (((IntPoint
)uvalue(ref
))%nhash(t
));
71 int lua_equalObj (Object
*t1
, Object
*t2
)
73 if (tag(t1
) != tag(t2
)) return 0;
76 case LUA_T_NIL
: return 1;
77 case LUA_T_NUMBER
: return nvalue(t1
) == nvalue(t2
);
78 case LUA_T_STRING
: return svalue(t1
) == svalue(t2
);
79 case LUA_T_ARRAY
: return avalue(t1
) == avalue(t2
);
80 case LUA_T_FUNCTION
: return t1
->value
.tf
== t2
->value
.tf
;
81 case LUA_T_CFUNCTION
: return fvalue(t1
) == fvalue(t2
);
82 default: return uvalue(t1
) == uvalue(t2
);
86 static int present (Hash
*t
, Object
*ref
)
88 int h
= hashindex(t
, ref
);
89 while (tag(ref(node(t
, h
))) != LUA_T_NIL
)
91 if (lua_equalObj(ref
, ref(node(t
, h
))))
100 ** Alloc a vector node
102 static Node
*hashnodecreate (int nhash
)
105 Node
*v
= newvector (nhash
, Node
);
106 for (i
=0; i
<nhash
; i
++)
107 tag(ref(&v
[i
])) = LUA_T_NIL
;
112 ** Create a new hash. Return the hash pointer or NULL on error.
114 static Hash
*hashcreate (int nhash
)
117 nhash
= luaI_redimension((int)((float)nhash
/REHASH_LIMIT
));
118 nodevector(t
) = hashnodecreate(nhash
);
128 static void hashdelete (Hash
*t
)
130 luaI_free (nodevector(t
));
136 ** Mark a hash and check its elements
138 void lua_hashmark (Hash
*h
)
140 if (markarray(h
) == 0)
144 for (i
=0; i
<nhash(h
); i
++)
147 if (tag(ref(n
)) != LUA_T_NIL
)
149 lua_markobject(&n
->ref
);
150 lua_markobject(&n
->val
);
157 static void call_fallbacks (void)
161 tag(&t
) = LUA_T_ARRAY
;
162 for (curr_array
= listhead
; curr_array
; curr_array
= curr_array
->next
)
163 if (markarray(curr_array
) != 1)
165 avalue(&t
) = curr_array
;
169 luaI_gcFB(&t
); /* end of list */
174 ** Garbage collection to arrays
175 ** Delete all unmarked arrays.
177 Long
lua_hashcollector (void)
179 Hash
*curr_array
= listhead
, *prev
= NULL
;
182 while (curr_array
!= NULL
)
184 Hash
*next
= curr_array
->next
;
185 if (markarray(curr_array
) != 1)
187 if (prev
== NULL
) listhead
= next
;
188 else prev
->next
= next
;
189 hashdelete(curr_array
);
194 markarray(curr_array
) = 0;
204 ** Create a new array
205 ** This function inserts the new array in the array list. It also
206 ** executes garbage collection if the number of arrays created
207 ** exceed a pre-defined range.
209 Hash
*lua_createarray (int nhash
)
213 array
= hashcreate(nhash
);
214 array
->next
= listhead
;
223 static void rehash (Hash
*t
)
227 Node
*vold
= nodevector(t
);
228 nhash(t
) = luaI_redimension(nhash(t
));
229 nodevector(t
) = hashnodecreate(nhash(t
));
230 for (i
=0; i
<nold
; i
++)
233 if (tag(ref(n
)) != LUA_T_NIL
&& tag(val(n
)) != LUA_T_NIL
)
234 *node(t
, present(t
, ref(n
))) = *n
; /* copy old node to new hahs */
240 ** If the hash node is present, return its pointer, otherwise return
243 Object
*lua_hashget (Hash
*t
, Object
*ref
)
245 int h
= present(t
, ref
);
246 if (tag(ref(node(t
, h
))) != LUA_T_NIL
) return val(node(t
, h
));
252 ** If the hash node is present, return its pointer, otherwise create a new
253 ** node for the given reference and also return its pointer.
255 Object
*lua_hashdefine (Hash
*t
, Object
*ref
)
261 if (tag(ref(n
)) == LUA_T_NIL
)
264 if ((float)nuse(t
) > (float)nhash(t
)*REHASH_LIMIT
)
271 tag(val(n
)) = LUA_T_NIL
;
278 ** Internal function to manipulate arrays.
279 ** Given an array object and a reference value, return the next element
281 ** This function pushs the element value and its reference to the stack.
283 static void hashnext (Hash
*t
, int i
)
287 lua_pushnil(); lua_pushnil();
290 while (tag(ref(node(t
,i
))) == LUA_T_NIL
|| tag(val(node(t
,i
))) == LUA_T_NIL
)
294 lua_pushnil(); lua_pushnil();
298 luaI_pushobject(ref(node(t
,i
)));
299 luaI_pushobject(val(node(t
,i
)));
305 lua_Object o
= lua_getparam(1);
306 lua_Object r
= lua_getparam(2);
307 if (o
== LUA_NOOBJECT
|| r
== LUA_NOOBJECT
)
308 lua_error ("too few arguments to function `next'");
309 if (lua_getparam(3) != LUA_NOOBJECT
)
310 lua_error ("too many arguments to function `next'");
312 lua_error ("first argument of function `next' is not a table");
313 t
= avalue(luaI_Address(o
));
320 int h
= present (t
, luaI_Address(r
));