From d766e2ae175495da85714d00e61d76174c5acc5b Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Sun, 25 Feb 2018 09:48:16 -0300 Subject: [PATCH] first (parcial) implementation of 'keyin'/'removekey' (still no metamethods, no raw verssions) --- lapi.c | 92 ++++++++++++++++++++++++++++++++++-------------------- lbaselib.c | 22 ++++++++++++- lobject.h | 17 +++++++--- ltablib.c | 6 ++-- lua.h | 4 ++- 5 files changed, 98 insertions(+), 43 deletions(-) diff --git a/lapi.c b/lapi.c index 0debc1d3..b6c52721 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.285 2018/02/20 16:52:50 roberto Exp roberto $ +** $Id: lapi.c,v 2.286 2018/02/23 13:13:31 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -668,35 +668,65 @@ static int finishrawget (lua_State *L, const TValue *val) { } +static Table *gettable (lua_State *L, int idx) { + TValue *t = index2value(L, idx); + api_check(L, ttistable(t), "table expected"); + return hvalue(t); +} + + LUA_API int lua_rawget (lua_State *L, int idx) { - TValue *t; + Table *t; const TValue *val; lua_lock(L); - t = index2value(L, idx); - api_check(L, ttistable(t), "table expected"); - val = luaH_get(hvalue(t), s2v(L->top - 1)); + t = gettable(L, idx); + val = luaH_get(t, s2v(L->top - 1)); L->top--; /* remove key */ return finishrawget(L, val); } LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { - TValue *t; + Table *t; lua_lock(L); - t = index2value(L, idx); - api_check(L, ttistable(t), "table expected"); - return finishrawget(L, luaH_getint(hvalue(t), n)); + t = gettable(L, idx); + return finishrawget(L, luaH_getint(t, n)); } LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { - TValue *t; + Table *t; TValue k; lua_lock(L); - t = index2value(L, idx); - api_check(L, ttistable(t), "table expected"); + t = gettable(L, idx); setpvalue(&k, cast_voidp(p)); - return finishrawget(L, luaH_get(hvalue(t), &k)); + return finishrawget(L, luaH_get(t, &k)); +} + + +static int auxkeyman (lua_State *L, int idx, int remove) { + Table *t; + const TValue *val; + int res; + lua_lock(L); + t = gettable(L, idx); + val = luaH_get(t, s2v(L->top - 1)); + L->top--; /* remove key */ + res = !isempty(val); + if (remove && res) /* key is present and should be removed? */ + setempty(cast(TValue*, val)); + lua_unlock(L); + return res; +} + + +LUA_API void lua_removekey (lua_State *L, int idx) { + auxkeyman(L, idx, 1); +} + + +LUA_API int lua_keyin (lua_State *L, int idx) { + return auxkeyman(L, idx, 0); } @@ -834,45 +864,42 @@ LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { LUA_API void lua_rawset (lua_State *L, int idx) { - TValue *o; + Table *t; TValue *slot; lua_lock(L); api_checknelems(L, 2); - o = index2value(L, idx); - api_check(L, ttistable(o), "table expected"); - slot = luaH_set(L, hvalue(o), s2v(L->top - 2)); + t = gettable(L, idx); + slot = luaH_set(L, t, s2v(L->top - 2)); setobj2t(L, slot, s2v(L->top - 1)); - invalidateTMcache(hvalue(o)); - luaC_barrierback(L, gcvalue(o), s2v(L->top - 1)); + invalidateTMcache(t); + luaC_barrierback(L, obj2gco(t), s2v(L->top - 1)); L->top -= 2; lua_unlock(L); } LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { - TValue *o; + Table *t; lua_lock(L); api_checknelems(L, 1); - o = index2value(L, idx); - api_check(L, ttistable(o), "table expected"); - luaH_setint(L, hvalue(o), n, s2v(L->top - 1)); - luaC_barrierback(L, gcvalue(o), s2v(L->top - 1)); + t = gettable(L, idx); + luaH_setint(L, t, n, s2v(L->top - 1)); + luaC_barrierback(L, obj2gco(t), s2v(L->top - 1)); L->top--; lua_unlock(L); } LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { - TValue *o; + Table *t; TValue k, *slot; lua_lock(L); api_checknelems(L, 1); - o = index2value(L, idx); - api_check(L, ttistable(o), "table expected"); + t = gettable(L, idx); setpvalue(&k, cast_voidp(p)); - slot = luaH_set(L, hvalue(o), &k); + slot = luaH_set(L, t, &k); setobj2t(L, slot, s2v(L->top - 1)); - luaC_barrierback(L, gcvalue(o), s2v(L->top - 1)); + luaC_barrierback(L, obj2gco(t), s2v(L->top - 1)); L->top--; lua_unlock(L); } @@ -1193,12 +1220,11 @@ LUA_API int lua_error (lua_State *L) { LUA_API int lua_next (lua_State *L, int idx) { - TValue *t; + Table *t; int more; lua_lock(L); - t = index2value(L, idx); - api_check(L, ttistable(t), "table expected"); - more = luaH_next(L, hvalue(t), L->top - 1); + t = gettable(L, idx); + more = luaH_next(L, t, L->top - 1); if (more) { api_incr_top(L); } diff --git a/lbaselib.c b/lbaselib.c index c95a6e53..443bf066 100644 --- a/lbaselib.c +++ b/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.318 2017/11/16 13:19:06 roberto Exp roberto $ +** $Id: lbaselib.c,v 1.319 2018/02/05 17:10:52 roberto Exp roberto $ ** Basic library ** See Copyright Notice in lua.h */ @@ -170,6 +170,24 @@ static int luaB_rawset (lua_State *L) { } +static int luaB_keyin (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_pushboolean(L, lua_keyin(L, 1)); + return 1; +} + + +static int luaB_removekey (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_removekey(L, 1); + return 0; +} + + static int pushmode (lua_State *L, int oldmode) { lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental" : "generational"); return 1; @@ -501,6 +519,8 @@ static const luaL_Reg base_funcs[] = { {"rawlen", luaB_rawlen}, {"rawget", luaB_rawget}, {"rawset", luaB_rawset}, + {"keyin", luaB_keyin}, + {"removekey", luaB_removekey}, {"select", luaB_select}, {"setmetatable", luaB_setmetatable}, {"tonumber", luaB_tonumber}, diff --git a/lobject.h b/lobject.h index c6590cf0..da110128 100644 --- a/lobject.h +++ b/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 2.136 2018/02/22 17:28:10 roberto Exp roberto $ +** $Id: lobject.h,v 2.137 2018/02/23 13:13:31 roberto Exp roberto $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -156,13 +156,20 @@ typedef StackValue *StkId; /* index to stack elements */ #define LUA_TEMPTY (LUA_TNIL | (1 << 4)) #define ttisnilorempty(v) checktype((v), LUA_TNIL) -/* -** By default, entries with any kind of nil are considered empty -*/ -#define isempty(v) ttisnilorempty(v) #define isreallyempty(v) checktag((v), LUA_TEMPTY) + +#if defined(LUA_NILINTABLE) + +#define isempty(v) isreallyempty(v) + +#else /* By default, entries with any kind of nil are considered empty */ + +#define isempty(v) ttisnilorempty(v) + +#endif + /* macro defining an empty value */ #define EMPTYCONSTANT {NULL}, LUA_TEMPTY diff --git a/ltablib.c b/ltablib.c index 588bf40d..982821ed 100644 --- a/ltablib.c +++ b/ltablib.c @@ -1,5 +1,5 @@ /* -** $Id: ltablib.c,v 1.92 2016/02/08 12:55:19 roberto Exp roberto $ +** $Id: ltablib.c,v 1.93 2016/02/25 19:41:54 roberto Exp roberto $ ** Library for Table Manipulation ** See Copyright Notice in lua.h */ @@ -113,8 +113,8 @@ static int tremove (lua_State *L) { lua_geti(L, 1, pos + 1); lua_seti(L, 1, pos); /* t[pos] = t[pos + 1] */ } - lua_pushnil(L); - lua_seti(L, 1, pos); /* t[pos] = nil */ + lua_pushinteger(L, pos); + lua_removekey(L, 1); /* remove entry t[pos] */ return 1; } diff --git a/lua.h b/lua.h index 8fb2ccbe..3c481a70 100644 --- a/lua.h +++ b/lua.h @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.340 2018/02/17 19:29:29 roberto Exp roberto $ +** $Id: lua.h,v 1.341 2018/02/20 16:52:50 roberto Exp roberto $ ** Lua - A Scripting Language ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this file @@ -331,6 +331,8 @@ LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s); LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); +LUA_API void (lua_removekey) (lua_State *L, int idx); +LUA_API int (lua_keyin) (lua_State *L, int idx); /*