2 ** $Id: ltable.c,v 1.12 1998/01/28 16:50:33 roberto Exp $
4 ** See Copyright Notice in lua.h
17 #define gcsize(n) (1+(n/16))
19 #define nuse(t) ((t)->nuse)
20 #define nodevector(t) ((t)->node)
23 #define REHASH_LIMIT 0.70 /* avoid more than this % full */
25 #define TagDefault LUA_T_ARRAY;
29 static long int hashindex (TObject
*ref
)
34 h
= (long int)nvalue(ref
);
36 case LUA_T_STRING
: case LUA_T_USERDATA
:
37 h
= (IntPoint
)tsvalue(ref
);
40 h
= (IntPoint
)avalue(ref
);
43 h
= (IntPoint
)tfvalue(ref
);
46 h
= (IntPoint
)fvalue(ref
);
49 h
= (IntPoint
)clvalue(ref
);
52 lua_error("unexpected type to index table");
53 h
= 0; /* to avoid warnings */
55 return (h
>= 0 ? h
: -(h
+1));
59 static int present (Hash
*t
, TObject
*key
)
62 long int h
= hashindex(key
);
64 TObject
*rf
= ref(node(t
, h1
));
65 if (ttype(rf
) != LUA_T_NIL
&& !luaO_equalObj(key
, rf
)) {
66 int h2
= h
%(tsize
-2) + 1;
69 if (h1
>= tsize
) h1
-= tsize
;
70 rf
= ref(node(t
, h1
));
71 } while (ttype(rf
) != LUA_T_NIL
&& !luaO_equalObj(key
, rf
));
78 ** Alloc a vector node
80 static Node
*hashnodecreate (int nhash
)
82 Node
*v
= luaM_newvector(nhash
, Node
);
84 for (i
=0; i
<nhash
; i
++)
85 ttype(ref(&v
[i
])) = LUA_T_NIL
;
92 static void hashdelete (Hash
*t
)
94 luaM_free(nodevector(t
));
99 void luaH_free (Hash
*frees
)
102 Hash
*next
= (Hash
*)frees
->head
.next
;
103 L
->nblocks
-= gcsize(frees
->nhash
);
110 Hash
*luaH_new (int nhash
)
112 Hash
*t
= luaM_new(Hash
);
113 nhash
= luaO_redimension((int)((float)nhash
/REHASH_LIMIT
));
114 nodevector(t
) = hashnodecreate(nhash
);
117 t
->htag
= TagDefault
;
118 luaO_insertlist(&(L
->roottable
), (GCnode
*)t
);
119 L
->nblocks
+= gcsize(nhash
);
124 static int newsize (Hash
*t
)
130 for (i
=0; i
<size
; i
++) {
131 if (ttype(ref(v
+i
)) != LUA_T_NIL
&& ttype(val(v
+i
)) != LUA_T_NIL
)
134 if (2*(realuse
+1) <= size
) /* +1 is the new element */
135 return size
; /* don't need to grow, just rehash */
137 return luaO_redimension(size
);
140 static void rehash (Hash
*t
)
143 Node
*vold
= nodevector(t
);
144 int nnew
= newsize(t
);
146 nodevector(t
) = hashnodecreate(nnew
);
148 for (i
=0; i
<nold
; i
++) {
150 if (ttype(ref(n
)) != LUA_T_NIL
&& ttype(val(n
)) != LUA_T_NIL
)
151 *node(t
, present(t
, ref(n
))) = *n
; /* copy old node to luaM_new hash */
153 L
->nblocks
+= gcsize(nnew
)-gcsize(nold
);
158 ** If the hash node is present, return its pointer, otherwise return
161 TObject
*luaH_get (Hash
*t
, TObject
*ref
)
163 int h
= present(t
, ref
);
164 if (ttype(ref(node(t
, h
))) != LUA_T_NIL
) return val(node(t
, h
));
170 ** If the hash node is present, return its pointer, otherwise create a luaM_new
171 ** node for the given reference and also return its pointer.
173 TObject
*luaH_set (Hash
*t
, TObject
*ref
)
175 Node
*n
= node(t
, present(t
, ref
));
176 if (ttype(ref(n
)) == LUA_T_NIL
) {
178 if ((float)nuse(t
) > (float)nhash(t
)*REHASH_LIMIT
) {
180 n
= node(t
, present(t
, ref
));
183 ttype(val(n
)) = LUA_T_NIL
;
189 static Node
*hashnext (Hash
*t
, int i
)
192 int tsize
= nhash(t
);
196 while (ttype(ref(n
)) == LUA_T_NIL
|| ttype(val(n
)) == LUA_T_NIL
) {
204 Node
*luaH_next (TObject
*o
, TObject
*r
)
207 if (ttype(r
) == LUA_T_NIL
)
208 return hashnext(t
, 0);
210 int i
= present(t
, r
);
211 Node
*n
= node(t
, i
);
212 luaL_arg_check(ttype(ref(n
))!=LUA_T_NIL
&& ttype(val(n
))!=LUA_T_NIL
,
214 return hashnext(t
, i
+1);