3 ** hash manager for lua
6 char *rcs_hash
="$Id: hash.c,v 2.43 1997/05/14 18:38:29 roberto Exp $";
17 #define nhash(t) ((t)->nhash)
18 #define nuse(t) ((t)->nuse)
19 #define markarray(t) ((t)->mark)
20 #define nodevector(t) ((t)->node)
21 #define node(t,i) (&(t)->node[i])
22 #define ref(n) (&(n)->ref)
23 #define val(n) (&(n)->val)
26 #define REHASH_LIMIT 0.70 /* avoid more than this % full */
28 #define TagDefault LUA_T_ARRAY;
31 static Hash
*listhead
= NULL
;
34 /* hash dimensions values */
35 static Long dimensions
[] =
36 {5L, 11L, 23L, 47L, 97L, 197L, 397L, 797L, 1597L, 3203L, 6421L,
37 12853L, 25717L, 51437L, 102811L, 205619L, 411233L, 822433L,
38 1644817L, 3289613L, 6579211L, 13158023L, MAX_INT
};
40 int luaI_redimension (int nhash
)
43 for (i
=0; dimensions
[i
]<MAX_INT
; i
++)
45 if (dimensions
[i
] > nhash
)
48 lua_error("table overflow");
49 return 0; /* to avoid warnings */
53 int lua_equalObj (TObject
*t1
, TObject
*t2
)
55 if (ttype(t1
) != ttype(t2
)) return 0;
58 case LUA_T_NIL
: return 1;
59 case LUA_T_NUMBER
: return nvalue(t1
) == nvalue(t2
);
60 case LUA_T_STRING
: case LUA_T_USERDATA
: return svalue(t1
) == svalue(t2
);
61 case LUA_T_ARRAY
: return avalue(t1
) == avalue(t2
);
62 case LUA_T_FUNCTION
: return t1
->value
.tf
== t2
->value
.tf
;
63 case LUA_T_CFUNCTION
: return fvalue(t1
) == fvalue(t2
);
65 lua_error("internal error in `lua_equalObj'");
66 return 0; /* UNREACHEABLE */
71 static long int hashindex (TObject
*ref
)
76 h
= (long int)nvalue(ref
); break;
77 case LUA_T_STRING
: case LUA_T_USERDATA
:
78 h
= tsvalue(ref
)->hash
; break;
80 h
= (IntPoint
)ref
->value
.tf
; break;
82 h
= (IntPoint
)fvalue(ref
); break;
84 h
= (IntPoint
)avalue(ref
); break;
86 lua_error ("unexpected type to index table");
87 h
= 0; /* UNREACHEABLE */
94 static int present (Hash
*t
, TObject
*key
)
96 long int h
= hashindex(key
);
99 TObject
*rf
= ref(node(t
, h1
));
100 if (ttype(rf
) != LUA_T_NIL
&& !lua_equalObj(key
, rf
)) {
101 int h2
= h
%(tsize
-2) + 1;
104 rf
= ref(node(t
, h1
));
105 } while (ttype(rf
) != LUA_T_NIL
&& !lua_equalObj(key
, rf
));
112 ** Alloc a vector node
114 static Node
*hashnodecreate (int nhash
)
117 Node
*v
= newvector (nhash
, Node
);
118 for (i
=0; i
<nhash
; i
++)
119 ttype(ref(&v
[i
])) = LUA_T_NIL
;
124 ** Create a new hash. Return the hash pointer or NULL on error.
126 static Hash
*hashcreate (int nhash
)
129 nhash
= luaI_redimension((int)((float)nhash
/REHASH_LIMIT
));
130 nodevector(t
) = hashnodecreate(nhash
);
134 t
->htag
= TagDefault
;
141 static void hashdelete (Hash
*t
)
143 luaI_free (nodevector(t
));
149 ** Mark a hash and check its elements
151 void lua_hashmark (Hash
*h
)
153 if (markarray(h
) == 0)
157 for (i
=0; i
<nhash(h
); i
++)
160 if (ttype(ref(n
)) != LUA_T_NIL
)
162 lua_markobject(&n
->ref
);
163 lua_markobject(&n
->val
);
170 void luaI_hashcallIM (Hash
*l
)
173 ttype(&t
) = LUA_T_ARRAY
;
174 for (; l
; l
=l
->next
) {
181 void luaI_hashfree (Hash
*frees
)
184 Hash
*next
= frees
->next
;
191 Hash
*luaI_hashcollector (long *acum
)
193 Hash
*curr_array
= listhead
, *prev
= NULL
, *frees
= NULL
;
195 while (curr_array
!= NULL
) {
196 Hash
*next
= curr_array
->next
;
197 if (markarray(curr_array
) != 1) {
202 curr_array
->next
= frees
;
207 markarray(curr_array
) = 0;
218 ** Create a new array
219 ** This function inserts the new array in the array list. It also
220 ** executes garbage collection if the number of arrays created
221 ** exceed a pre-defined range.
223 Hash
*lua_createarray (int nhash
)
227 array
= hashcreate(nhash
);
228 array
->next
= listhead
;
236 ** Check if table has deleted slots. It it has, it does not need to
237 ** grow, since rehash will reuse them.
239 static int emptyslots (Hash
*t
)
242 for (i
=nhash(t
)-1; i
>=0; i
--) {
243 Node
*n
= node(t
, i
);
244 if (ttype(ref(n
)) != LUA_T_NIL
&& ttype(val(n
)) == LUA_T_NIL
)
250 static void rehash (Hash
*t
)
253 Node
*vold
= nodevector(t
);
256 nhash(t
) = luaI_redimension(nhash(t
));
257 nodevector(t
) = hashnodecreate(nhash(t
));
258 for (i
=0; i
<nold
; i
++) {
260 if (ttype(ref(n
)) != LUA_T_NIL
&& ttype(val(n
)) != LUA_T_NIL
)
261 *node(t
, present(t
, ref(n
))) = *n
; /* copy old node to new hash */
267 ** If the hash node is present, return its pointer, otherwise return
270 TObject
*lua_hashget (Hash
*t
, TObject
*ref
)
272 int h
= present(t
, ref
);
273 if (ttype(ref(node(t
, h
))) != LUA_T_NIL
) return val(node(t
, h
));
279 ** If the hash node is present, return its pointer, otherwise create a new
280 ** node for the given reference and also return its pointer.
282 TObject
*lua_hashdefine (Hash
*t
, TObject
*ref
)
284 Node
*n
= node(t
, present(t
, ref
));
285 if (ttype(ref(n
)) == LUA_T_NIL
) {
287 if ((float)nuse(t
) > (float)nhash(t
)*REHASH_LIMIT
) {
289 n
= node(t
, present(t
, ref
));
292 ttype(val(n
)) = LUA_T_NIL
;
299 ** Internal function to manipulate arrays.
300 ** Given an array object and a reference value, return the next element
302 ** This function pushs the element value and its reference to the stack.
304 static void hashnext (Hash
*t
, int i
)
307 int tsize
= nhash(t
);
311 while (ttype(ref(n
)) == LUA_T_NIL
|| ttype(val(n
)) == LUA_T_NIL
) {
316 luaI_pushobject(ref(node(t
,i
)));
317 luaI_pushobject(val(node(t
,i
)));
323 lua_Object o
= lua_getparam(1);
324 lua_Object r
= lua_getparam(2);
325 luaL_arg_check(lua_istable(o
), 1, "table expected");
326 luaL_arg_check(r
!= LUA_NOOBJECT
, 2, "value expected");
327 t
= avalue(luaI_Address(o
));
331 hashnext(t
, present(t
, luaI_Address(r
))+1);