Imported from ../lua-1.0.tar.gz.
[lua.git] / hash.c
blob8743d52cee07d526a92018955f1bfcc9281c0006
1 /*
2 ** hash.c
3 ** hash manager for lua
4 ** Luiz Henrique de Figueiredo - 17 Aug 90
5 ** Modified by Waldemar Celes Filho
6 ** 12 May 93
7 */
9 #include <string.h>
10 #include <stdlib.h>
12 #include "opcode.h"
13 #include "hash.h"
14 #include "inout.h"
15 #include "table.h"
16 #include "lua.h"
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)
36 int h;
37 char *name = svalue(ref);
38 for (h=0; *name!=0; name++) /* interpret name as binary number */
40 h <<= 8;
41 h += (unsigned char) *name; /* avoid sign extension */
42 h %= nhash(t); /* make it a valid index */
44 return h;
46 else
48 lua_reportbug ("unexpected type to index table");
49 return -1;
53 static Node *present(Hash *t, Object *ref, int h)
55 Node *n=NULL, *p;
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 */
67 return NULL;
68 #if 0
69 if (p!=NULL) /* name present but not first */
71 p->next=n->next; /* move-to-front self-organization */
72 n->next=list(t,h);
73 list(t,h)=n;
75 #endif
76 return n;
79 static void freelist (Node *n)
81 while (n)
83 Node *next = n->next;
84 free (n);
85 n = next;
90 ** Create a new hash. Return the hash pointer or NULL on error.
92 Hash *lua_hashcreate (unsigned int nhash)
94 Hash *t = new (Hash);
95 if (t == NULL)
97 lua_error ("not enough memory");
98 return NULL;
100 nhash(t) = nhash;
101 markarray(t) = 0;
102 nodelist(t) = newvector (nhash, Node*);
103 if (nodelist(t) == NULL)
105 lua_error ("not enough memory");
106 return NULL;
108 return t;
112 ** Delete a hash
114 void lua_hashdelete (Hash *h)
116 int i;
117 for (i=0; i<nhash(h); i++)
118 freelist (list(h,i));
119 free (nodelist(h));
120 free(h);
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)
130 int h;
131 Node *n;
132 h = head (t, ref);
133 if (h < 0) return NULL;
135 n = present(t, ref, h);
136 if (n == NULL)
138 n = new(Node);
139 if (n == NULL)
141 lua_error ("not enough memory");
142 return NULL;
144 n->ref = *ref;
145 tag(&n->val) = T_NIL;
146 n->next = list(t,h); /* link node to head of list */
147 list(t,h) = n;
149 return (&n->val);
153 ** Mark a hash and check its elements
155 void lua_hashmark (Hash *h)
157 int i;
159 markarray(h) = 1;
161 for (i=0; i<nhash(h); i++)
163 Node *n;
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
176 ** in the hash.
177 ** This function pushs the element value and its reference to the stack.
179 #include "lua.h"
180 static void firstnode (Hash *a, int h)
182 if (h < nhash(a))
184 int i;
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);
191 return;
195 lua_pushnil();
196 lua_pushnil();
198 void lua_next (void)
200 Hash *a;
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; }
209 a = avalue(o);
210 if (tag(r) == T_NIL)
212 firstnode (a, 0);
213 return;
215 else
217 int h = head (a, r);
218 if (h >= 0)
220 Node *n = list(a,h);
221 while (n)
223 if (memcmp(&n->ref,r,sizeof(Object)) == 0)
225 if (n->next == NULL)
227 firstnode (a, h+1);
228 return;
230 else if (tag(&n->next->val) != T_NIL)
232 lua_pushobject (&n->next->ref);
233 lua_pushobject (&n->next->val);
234 return;
236 else
238 Node *next = n->next->next;
239 while (next != NULL && tag(&next->val) == T_NIL) next = next->next;
240 if (next == NULL)
242 firstnode (a, h+1);
243 return;
245 else
247 lua_pushobject (&next->ref);
248 lua_pushobject (&next->val);
250 return;
253 n = n->next;
255 if (n == NULL)
256 lua_error ("error in function 'next': reference not found");