aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ltable.c58
1 files changed, 14 insertions, 44 deletions
diff --git a/ltable.c b/ltable.c
index ea3ab4a9..c6f67fd5 100644
--- a/ltable.c
+++ b/ltable.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltable.c,v 1.30 1999/11/22 13:12:07 roberto Exp roberto $ 2** $Id: ltable.c,v 1.31 1999/11/26 18:59:20 roberto Exp roberto $
3** Lua tables (hash) 3** Lua tables (hash)
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -40,7 +40,7 @@
40** returns the `main' position of an element in a table (that is, the index 40** returns the `main' position of an element in a table (that is, the index
41** of its hash value) 41** of its hash value)
42*/ 42*/
43Node *luaH_mainposition (lua_State *L, const Hash *t, const TObject *key) { 43Node *luaH_mainposition (const Hash *t, const TObject *key) {
44 unsigned long h; 44 unsigned long h;
45 switch (ttype(key)) { 45 switch (ttype(key)) {
46 case LUA_T_NUMBER: 46 case LUA_T_NUMBER:
@@ -62,8 +62,7 @@ Node *luaH_mainposition (lua_State *L, const Hash *t, const TObject *key) {
62 h = IntPoint(L, clvalue(key)); 62 h = IntPoint(L, clvalue(key));
63 break; 63 break;
64 default: 64 default:
65 lua_error(L, "unexpected type to index table"); 65 return NULL; /* invalid key */
66 h = 0; /* to avoid warnings */
67 } 66 }
68 LUA_ASSERT(L, h%(unsigned int)t->size == (h&((unsigned int)t->size-1)), 67 LUA_ASSERT(L, h%(unsigned int)t->size == (h&((unsigned int)t->size-1)),
69 "a&(x-1) == a%x, for x power of 2"); 68 "a&(x-1) == a%x, for x power of 2");
@@ -72,13 +71,15 @@ Node *luaH_mainposition (lua_State *L, const Hash *t, const TObject *key) {
72 71
73 72
74const TObject *luaH_get (lua_State *L, const Hash *t, const TObject *key) { 73const TObject *luaH_get (lua_State *L, const Hash *t, const TObject *key) {
75 Node *n = luaH_mainposition(L, t, key); 74 Node *n = luaH_mainposition(t, key);
76 do { 75 if (!n)
76 lua_error(L, "unexpected type to index table");
77 else do {
77 if (luaO_equalObj(key, &n->key)) 78 if (luaO_equalObj(key, &n->key))
78 return &n->val; 79 return &n->val;
79 n = n->next; 80 n = n->next;
80 } while (n); 81 } while (n);
81 return &luaO_nilobject; 82 return &luaO_nilobject; /* key not found */
82} 83}
83 84
84 85
@@ -140,49 +141,16 @@ static int newsize (const Hash *t) {
140} 141}
141 142
142 143
143/*
144** the rehash is done in two stages: first, we insert only the elements whose
145** main position is free, to avoid needless collisions. In the second stage,
146** we insert the other elements.
147*/
148static void rehash (lua_State *L, Hash *t) { 144static void rehash (lua_State *L, Hash *t) {
149 int oldsize = t->size; 145 int oldsize = t->size;
150 Node *nold = t->node; 146 Node *nold = t->node;
151 int i; 147 int i;
152 L->nblocks -= gcsize(L, oldsize); 148 L->nblocks -= gcsize(L, oldsize);
153 setnodevector(L, t, newsize(t)); /* create new array of nodes */ 149 setnodevector(L, t, newsize(t)); /* create new array of nodes */
154 /* first loop; set only elements that can go in their main positions */
155 for (i=0; i<oldsize; i++) { 150 for (i=0; i<oldsize; i++) {
156 Node *old = nold+i; 151 Node *old = nold+i;
157 if (ttype(&old->val) == LUA_T_NIL) 152 if (ttype(&old->val) != LUA_T_NIL)
158 old->next = NULL; /* `remove' it for next loop */ 153 luaH_set(L, t, &old->key, &old->val);
159 else {
160 Node *mp = luaH_mainposition(L, t, &old->key); /* new main position */
161 if (ttype(&mp->key) == LUA_T_NIL) { /* is it empty? */
162 mp->key = old->key; /* put element there */
163 mp->val = old->val;
164 old->next = NULL; /* `remove' it for next loop */
165 }
166 else /* it will be copied in next loop */
167 old->next = mp; /* to be used in next loop */
168 }
169 }
170 /* update `firstfree' */
171 while (ttype(&t->firstfree->key) != LUA_T_NIL) t->firstfree--;
172 /* second loop; update elements with colision */
173 for (i=0; i<oldsize; i++) {
174 Node *old = nold+i;
175 if (old->next) { /* wasn't already `removed'? */
176 Node *mp = old->next; /* main position */
177 Node *e = t->firstfree; /* actual position */
178 e->key = old->key; /* put element in the free position */
179 e->val = old->val;
180 e->next = mp->next; /* chain actual position in main position's list */
181 mp->next = e;
182 do { /* update `firstfree' */
183 t->firstfree--;
184 } while (ttype(&t->firstfree->key) != LUA_T_NIL);
185 }
186 } 154 }
187 luaM_free(L, nold); /* free old array */ 155 luaM_free(L, nold); /* free old array */
188} 156}
@@ -202,8 +170,10 @@ static void rehash (lua_State *L, Hash *t) {
202** (this happens when we use `luaH_move'), there is no problem. 170** (this happens when we use `luaH_move'), there is no problem.
203*/ 171*/
204void luaH_set (lua_State *L, Hash *t, const TObject *key, const TObject *val) { 172void luaH_set (lua_State *L, Hash *t, const TObject *key, const TObject *val) {
205 Node *mp = luaH_mainposition(L, t, key); 173 Node *mp = luaH_mainposition(t, key);
206 Node *n = mp; 174 Node *n = mp;
175 if (!mp)
176 lua_error(L, "unexpected type to index table");
207 do { /* check whether `key' is somewhere in the chain */ 177 do { /* check whether `key' is somewhere in the chain */
208 if (luaO_equalObj(key, &n->key)) { 178 if (luaO_equalObj(key, &n->key)) {
209 n->val = *val; /* update value */ 179 n->val = *val; /* update value */
@@ -217,7 +187,7 @@ void luaH_set (lua_State *L, Hash *t, const TObject *key, const TObject *val) {
217 n = t->firstfree; /* get a free place */ 187 n = t->firstfree; /* get a free place */
218 /* is colliding node out of its main position? (can only happens if 188 /* is colliding node out of its main position? (can only happens if
219 its position if after "firstfree") */ 189 its position if after "firstfree") */
220 if (mp > n && (othern=luaH_mainposition(L, t, &mp->key)) != mp) { 190 if (mp > n && (othern=luaH_mainposition(t, &mp->key)) != mp) {
221 /* yes; move colliding node into free position */ 191 /* yes; move colliding node into free position */
222 while (othern->next != mp) othern = othern->next; /* find previous */ 192 while (othern->next != mp) othern = othern->next; /* find previous */
223 othern->next = n; /* redo the chain with `n' in place of `mp' */ 193 othern->next = n; /* redo the chain with `n' in place of `mp' */