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' */ |
