فهرست منبع

first (parcial) implementation of 'keyin'/'removekey'
(still no metamethods, no raw verssions)

Roberto Ierusalimschy 7 سال پیش
والد
کامیت
d766e2ae17
5فایلهای تغییر یافته به همراه98 افزوده شده و 43 حذف شده
  1. 59 33
      lapi.c
  2. 21 1
      lbaselib.c
  3. 12 5
      lobject.h
  4. 3 3
      ltablib.c
  5. 3 1
      lua.h

+ 59 - 33
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);
   }

+ 21 - 1
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},

+ 12 - 5
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
 

+ 3 - 3
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;
 }
 

+ 3 - 1
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);
 
 
 /*