3 ** hash manager for lua
4 ** Luiz Henrique de Figueiredo - 17 Aug 90
5 ** Modified by Waldemar Celes Filho
18 #define streq(s1,s2) (strcmp(s1,s2)==0)
19 #define strneq(s1,s2) (strcmp(s1,s2)!=0)
21 #define new(s) ((s *)malloc(sizeof(s)))
22 #define newvector(n,s) ((s *)calloc(n,sizeof(s)))
24 #define nhash(t) ((t)->nhash)
25 #define nodelist(t) ((t)->list)
26 #define list(t,i) ((t)->list[i])
27 #define ref_tag(n) (tag(&(n)->ref))
28 #define ref_nvalue(n) (nvalue(&(n)->ref))
29 #define ref_svalue(n) (svalue(&(n)->ref))
31 static int head (Hash
*t
, Object
*ref
) /* hash function */
33 if (tag(ref
) == T_NUMBER
) return (((int)nvalue(ref
))%nhash(t
));
34 else if (tag(ref
) == T_STRING
)
37 char *name
= svalue(ref
);
38 for (h
=0; *name
!=0; name
++) /* interpret name as binary number */
41 h
+= (unsigned char) *name
; /* avoid sign extension */
42 h
%= nhash(t
); /* make it a valid index */
48 lua_reportbug ("unexpected type to index table");
53 static Node
*present(Hash
*t
, Object
*ref
, int h
)
56 if (tag(ref
) == T_NUMBER
)
58 for (p
=NULL
,n
=list(t
,h
); n
!=NULL
; p
=n
, n
=n
->next
)
59 if (ref_tag(n
) == T_NUMBER
&& nvalue(ref
) == ref_nvalue(n
)) break;
61 else if (tag(ref
) == T_STRING
)
63 for (p
=NULL
,n
=list(t
,h
); n
!=NULL
; p
=n
, n
=n
->next
)
64 if (ref_tag(n
) == T_STRING
&& streq(svalue(ref
),ref_svalue(n
))) break;
66 if (n
==NULL
) /* name not present */
69 if (p
!=NULL
) /* name present but not first */
71 p
->next
=n
->next
; /* move-to-front self-organization */
79 static void freelist (Node
*n
)
90 ** Create a new hash. Return the hash pointer or NULL on error.
92 Hash
*lua_hashcreate (unsigned int nhash
)
97 lua_error ("not enough memory");
102 nodelist(t
) = newvector (nhash
, Node
*);
103 if (nodelist(t
) == NULL
)
105 lua_error ("not enough memory");
114 void lua_hashdelete (Hash
*h
)
117 for (i
=0; i
<nhash(h
); i
++)
118 freelist (list(h
,i
));
124 ** If the hash node is present, return its pointer, otherwise create a new
125 ** node for the given reference and also return its pointer.
126 ** On error, return NULL.
128 Object
*lua_hashdefine (Hash
*t
, Object
*ref
)
133 if (h
< 0) return NULL
;
135 n
= present(t
, ref
, h
);
141 lua_error ("not enough memory");
145 tag(&n
->val
) = T_NIL
;
146 n
->next
= list(t
,h
); /* link node to head of list */
153 ** Mark a hash and check its elements
155 void lua_hashmark (Hash
*h
)
161 for (i
=0; i
<nhash(h
); i
++)
164 for (n
= list(h
,i
); n
!= NULL
; n
= n
->next
)
166 lua_markobject (&n
->ref
);
167 lua_markobject (&n
->val
);
174 ** Internal function to manipulate arrays.
175 ** Given an array object and a reference value, return the next element
177 ** This function pushs the element value and its reference to the stack.
180 static void firstnode (Hash
*a
, int h
)
185 for (i
=h
; i
<nhash(a
); i
++)
187 if (list(a
,i
) != NULL
&& tag(&list(a
,i
)->val
) != T_NIL
)
189 lua_pushobject (&list(a
,i
)->ref
);
190 lua_pushobject (&list(a
,i
)->val
);
201 Object
*o
= lua_getparam (1);
202 Object
*r
= lua_getparam (2);
203 if (o
== NULL
|| r
== NULL
)
204 { lua_error ("too few arguments to function `next'"); return; }
205 if (lua_getparam (3) != NULL
)
206 { lua_error ("too many arguments to function `next'"); return; }
207 if (tag(o
) != T_ARRAY
)
208 { lua_error ("first argument of function `next' is not a table"); return; }
223 if (memcmp(&n
->ref
,r
,sizeof(Object
)) == 0)
230 else if (tag(&n
->next
->val
) != T_NIL
)
232 lua_pushobject (&n
->next
->ref
);
233 lua_pushobject (&n
->next
->val
);
238 Node
*next
= n
->next
->next
;
239 while (next
!= NULL
&& tag(&next
->val
) == T_NIL
) next
= next
->next
;
247 lua_pushobject (&next
->ref
);
248 lua_pushobject (&next
->val
);
256 lua_error ("error in function 'next': reference not found");