better (correct?) way to handle `next' over removed keys

This commit is contained in:
Roberto Ierusalimschy 2004-12-04 16:10:22 -02:00
parent 61a888518f
commit 531874f6ce
2 changed files with 18 additions and 9 deletions

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lobject.h,v 2.6 2004/10/06 18:34:16 roberto Exp $ ** $Id: lobject.h,v 2.7 2004/11/01 15:06:50 roberto Exp roberto $
** Type definitions for Lua objects ** Type definitions for Lua objects
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -25,6 +25,7 @@
*/ */
#define LUA_TPROTO (NUM_TAGS+1) #define LUA_TPROTO (NUM_TAGS+1)
#define LUA_TUPVAL (NUM_TAGS+2) #define LUA_TUPVAL (NUM_TAGS+2)
#define LUA_TDEADKEY (NUM_TAGS+3)
/* /*

View File

@ -1,5 +1,5 @@
/* /*
** $Id: ltable.c,v 2.10 2004/11/24 19:20:21 roberto Exp roberto $ ** $Id: ltable.c,v 2.11 2004/12/03 20:50:25 roberto Exp roberto $
** Lua tables (hash) ** Lua tables (hash)
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -122,7 +122,7 @@ static int arrayindex (const TValue *key) {
/* /*
** returns the index of a `key' for table traversals. First goes all ** returns the index of a `key' for table traversals. First goes all
** elements in the array part, then elements in the hash part. The ** elements in the array part, then elements in the hash part. The
** beginning and end of a traversal are signalled by -1. ** beginning of a traversal is signalled by -1.
*/ */
static int findindex (lua_State *L, Table *t, StkId key) { static int findindex (lua_State *L, Table *t, StkId key) {
int i; int i;
@ -131,12 +131,20 @@ static int findindex (lua_State *L, Table *t, StkId key) {
if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ if (0 < i && i <= t->sizearray) /* is `key' inside array part? */
return i-1; /* yes; that's the index (corrected to C) */ return i-1; /* yes; that's the index (corrected to C) */
else { else {
const TValue *v = luaH_get(t, key); Node *n = luaH_mainposition(t, key);
if (v == &luaO_nilobject) do { /* check whether `key' is somewhere in the chain */
luaG_runerror(L, "invalid key for `next'"); /* key may be dead already, but it is ok to use it in `next' */
i = cast(int, (cast(const lu_byte *, v) - if (luaO_rawequalObj(key2tval(n), key) ||
cast(const lu_byte *, gval(gnode(t, 0)))) / sizeof(Node)); (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) &&
return i + t->sizearray; /* hash elements are numbered after array ones */ gcvalue(gkey(n)) == gcvalue(key))) {
i = n - gnode(t, 0); /* key index in hash table */
/* hash elements are numbered after array ones */
return i + t->sizearray;
}
else n = gnext(n);
} while (n);
luaG_runerror(L, "invalid key for `next'"); /* key not found */
return 0; /* to avoid warnings */
} }
} }