From 46de77b219e381ff8553fdba0f52b319c00ea1e1 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Tue, 3 Nov 2015 13:47:30 -0200 Subject: [PATCH] bug: despite its name, 'luaH_getstr' did not work for strings in general, but only for short strings --- ltable.c | 51 +++++++++++++++++++++++++++++++++++---------------- ltable.h | 7 ++++++- ltm.c | 6 +++--- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/ltable.c b/ltable.c index 8a345062..e47b81f7 100644 --- a/ltable.c +++ b/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 2.112 2015/07/01 17:46:55 roberto Exp roberto $ +** $Id: ltable.c,v 2.113 2015/07/04 16:32:34 roberto Exp roberto $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -124,14 +124,8 @@ static Node *mainposition (const Table *t, const TValue *key) { return hashmod(t, l_hashfloat(fltvalue(key))); case LUA_TSHRSTR: return hashstr(t, tsvalue(key)); - case LUA_TLNGSTR: { - TString *s = tsvalue(key); - if (s->extra == 0) { /* no hash? */ - s->hash = luaS_hash(getstr(s), s->u.lnglen, s->hash); - s->extra = 1; /* now it has its hash */ - } - return hashstr(t, tsvalue(key)); - } + case LUA_TLNGSTR: + return hashpow2(t, luaS_hashlongstr(tsvalue(key))); case LUA_TBOOLEAN: return hashboolean(t, bvalue(key)); case LUA_TLIGHTUSERDATA: @@ -522,7 +516,7 @@ const TValue *luaH_getint (Table *t, lua_Integer key) { /* ** search function for short strings */ -const TValue *luaH_getstr (Table *t, TString *key) { +const TValue *luaH_getshortstr (Table *t, TString *key) { Node *n = hashstr(t, key); lua_assert(key->tt == LUA_TSHRSTR); for (;;) { /* check whether 'key' is somewhere in the chain */ @@ -531,11 +525,35 @@ const TValue *luaH_getstr (Table *t, TString *key) { return gval(n); /* that's it */ else { int nx = gnext(n); - if (nx == 0) break; + if (nx == 0) + return luaO_nilobject; /* not found */ n += nx; } - }; - return luaO_nilobject; + } +} + + +static const TValue *getlngstr (Table *t, TString *key) { + Node *n = hashpow2(t, luaS_hashlongstr(key)); + for (;;) { /* check whether 'key' is somewhere in the chain */ + const TValue *k = gkey(n); + if (ttislngstring(k) && luaS_eqlngstr(tsvalue(k), key)) + return gval(n); /* that's it */ + else { + int nx = gnext(n); + if (nx == 0) + return luaO_nilobject; /* not found */ + n += nx; + } + } +} + + +const TValue *luaH_getstr (Table *t, TString *key) { + if (key->tt == LUA_TSHRSTR) + return luaH_getshortstr(t, key); + else + return getlngstr(t, key); } @@ -544,7 +562,8 @@ const TValue *luaH_getstr (Table *t, TString *key) { */ const TValue *luaH_get (Table *t, const TValue *key) { switch (ttype(key)) { - case LUA_TSHRSTR: return luaH_getstr(t, tsvalue(key)); + case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key)); + case LUA_TLNGSTR: return getlngstr(t, tsvalue(key)); case LUA_TNUMINT: return luaH_getint(t, ivalue(key)); case LUA_TNIL: return luaO_nilobject; case LUA_TNUMFLT: { @@ -560,11 +579,11 @@ const TValue *luaH_get (Table *t, const TValue *key) { return gval(n); /* that's it */ else { int nx = gnext(n); - if (nx == 0) break; + if (nx == 0) + return luaO_nilobject; /* not found */ n += nx; } }; - return luaO_nilobject; } } } diff --git a/ltable.h b/ltable.h index 20ddacd0..bad66516 100644 --- a/ltable.h +++ b/ltable.h @@ -1,5 +1,5 @@ /* -** $Id: ltable.h,v 2.19 2014/07/29 16:22:24 roberto Exp roberto $ +** $Id: ltable.h,v 2.20 2014/09/04 18:15:29 roberto Exp roberto $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -18,6 +18,10 @@ /* 'const' to avoid wrong writings that can mess up field 'next' */ #define gkey(n) cast(const TValue*, (&(n)->i_key.tvk)) +/* +** writable version of 'gkey'; allows updates to individual fields, +** but not to the whole (which has incompatible type) +*/ #define wgkey(n) (&(n)->i_key.nk) #define invalidateTMcache(t) ((t)->flags = 0) @@ -31,6 +35,7 @@ LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value); +LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key); LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key); diff --git a/ltm.c b/ltm.c index 06408307..3f400d4b 100644 --- a/ltm.c +++ b/ltm.c @@ -1,5 +1,5 @@ /* -** $Id: ltm.c,v 2.34 2015/03/30 15:42:27 roberto Exp roberto $ +** $Id: ltm.c,v 2.35 2015/11/02 18:48:07 roberto Exp roberto $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -57,7 +57,7 @@ void luaT_init (lua_State *L) { ** tag methods */ const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { - const TValue *tm = luaH_getstr(events, ename); + const TValue *tm = luaH_getshortstr(events, ename); lua_assert(event <= TM_EQ); if (ttisnil(tm)) { /* no tag method? */ events->flags |= cast_byte(1u<mt[ttnov(o)]; } - return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); + return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : luaO_nilobject); }