diff options
-rw-r--r-- | ltable.c | 58 |
1 files changed, 14 insertions, 44 deletions
@@ -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 | */ |
43 | Node *luaH_mainposition (lua_State *L, const Hash *t, const TObject *key) { | 43 | Node *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 | ||
74 | const TObject *luaH_get (lua_State *L, const Hash *t, const TObject *key) { | 73 | const 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 | */ | ||
148 | static void rehash (lua_State *L, Hash *t) { | 144 | static 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 | */ |
204 | void luaH_set (lua_State *L, Hash *t, const TObject *key, const TObject *val) { | 172 | void 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' */ |