diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-02-27 14:48:28 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-02-27 14:48:28 -0300 |
commit | b7edf5d2d89ed2ce1e9087de496bcb451e39d131 (patch) | |
tree | 88d94c159ee2034fffd9195a60e306c9565bf361 | |
parent | ef8263f81fdde2310ebb15c9a3fe5e954d57cab5 (diff) | |
download | lua-b7edf5d2d89ed2ce1e9087de496bcb451e39d131.tar.gz lua-b7edf5d2d89ed2ce1e9087de496bcb451e39d131.tar.bz2 lua-b7edf5d2d89ed2ce1e9087de496bcb451e39d131.zip |
metamethods for 'removekey'/'keyin'
-rw-r--r-- | lapi.c | 19 | ||||
-rw-r--r-- | lbaselib.c | 8 | ||||
-rw-r--r-- | ltm.c | 31 | ||||
-rw-r--r-- | ltm.h | 6 |
4 files changed, 46 insertions, 18 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lapi.c,v 2.287 2018/02/25 12:48:16 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.288 2018/02/26 14:16:05 roberto Exp roberto $ |
3 | ** Lua API | 3 | ** Lua API |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -679,6 +679,7 @@ LUA_API int lua_rawget (lua_State *L, int idx) { | |||
679 | Table *t; | 679 | Table *t; |
680 | const TValue *val; | 680 | const TValue *val; |
681 | lua_lock(L); | 681 | lua_lock(L); |
682 | api_checknelems(L, 1); | ||
682 | t = gettable(L, idx); | 683 | t = gettable(L, idx); |
683 | val = luaH_get(t, s2v(L->top - 1)); | 684 | val = luaH_get(t, s2v(L->top - 1)); |
684 | L->top--; /* remove key */ | 685 | L->top--; /* remove key */ |
@@ -704,29 +705,24 @@ LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { | |||
704 | } | 705 | } |
705 | 706 | ||
706 | 707 | ||
707 | static int auxkeyman (lua_State *L, int idx, int remove) { | 708 | static int auxkeydef (lua_State *L, int idx, int remove) { |
708 | Table *t; | ||
709 | const TValue *val; | ||
710 | int res; | 709 | int res; |
711 | lua_lock(L); | 710 | lua_lock(L); |
712 | t = gettable(L, idx); | 711 | api_checknelems(L, 1); |
713 | val = luaH_get(t, s2v(L->top - 1)); | 712 | res = luaT_keydef(L, index2value(L, idx), s2v(L->top - 1), remove); |
714 | L->top--; /* remove key */ | 713 | L->top--; /* remove key */ |
715 | res = !isempty(val); | ||
716 | if (remove && res) /* key is present and should be removed? */ | ||
717 | setempty(cast(TValue*, val)); | ||
718 | lua_unlock(L); | 714 | lua_unlock(L); |
719 | return res; | 715 | return res; |
720 | } | 716 | } |
721 | 717 | ||
722 | 718 | ||
723 | LUA_API void lua_removekey (lua_State *L, int idx) { | 719 | LUA_API void lua_removekey (lua_State *L, int idx) { |
724 | auxkeyman(L, idx, 1); | 720 | auxkeydef(L, idx, 1); |
725 | } | 721 | } |
726 | 722 | ||
727 | 723 | ||
728 | LUA_API int lua_keyin (lua_State *L, int idx) { | 724 | LUA_API int lua_keyin (lua_State *L, int idx) { |
729 | return auxkeyman(L, idx, 0); | 725 | return auxkeydef(L, idx, 0); |
730 | } | 726 | } |
731 | 727 | ||
732 | 728 | ||
@@ -1223,6 +1219,7 @@ LUA_API int lua_next (lua_State *L, int idx) { | |||
1223 | Table *t; | 1219 | Table *t; |
1224 | int more; | 1220 | int more; |
1225 | lua_lock(L); | 1221 | lua_lock(L); |
1222 | api_checknelems(L, 1); | ||
1226 | t = gettable(L, idx); | 1223 | t = gettable(L, idx); |
1227 | more = luaH_next(L, t, L->top - 1); | 1224 | more = luaH_next(L, t, L->top - 1); |
1228 | if (more) { | 1225 | if (more) { |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbaselib.c,v 1.319 2018/02/05 17:10:52 roberto Exp roberto $ | 2 | ** $Id: lbaselib.c,v 1.320 2018/02/25 12:48:16 roberto Exp roberto $ |
3 | ** Basic library | 3 | ** Basic library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -171,8 +171,7 @@ static int luaB_rawset (lua_State *L) { | |||
171 | 171 | ||
172 | 172 | ||
173 | static int luaB_keyin (lua_State *L) { | 173 | static int luaB_keyin (lua_State *L) { |
174 | luaL_checktype(L, 1, LUA_TTABLE); | 174 | luaL_checkany(L, 2); /* ensures a first argument too */ |
175 | luaL_checkany(L, 2); | ||
176 | lua_settop(L, 2); | 175 | lua_settop(L, 2); |
177 | lua_pushboolean(L, lua_keyin(L, 1)); | 176 | lua_pushboolean(L, lua_keyin(L, 1)); |
178 | return 1; | 177 | return 1; |
@@ -180,8 +179,7 @@ static int luaB_keyin (lua_State *L) { | |||
180 | 179 | ||
181 | 180 | ||
182 | static int luaB_removekey (lua_State *L) { | 181 | static int luaB_removekey (lua_State *L) { |
183 | luaL_checktype(L, 1, LUA_TTABLE); | 182 | luaL_checkany(L, 2); /* ensures a first argument too */ |
184 | luaL_checkany(L, 2); | ||
185 | lua_settop(L, 2); | 183 | lua_settop(L, 2); |
186 | lua_removekey(L, 1); | 184 | lua_removekey(L, 1); |
187 | return 0; | 185 | return 0; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltm.c,v 2.64 2018/02/23 13:13:31 roberto Exp roberto $ | 2 | ** $Id: ltm.c,v 2.65 2018/02/26 14:16:05 roberto Exp roberto $ |
3 | ** Tag methods | 3 | ** Tag methods |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -38,6 +38,7 @@ LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = { | |||
38 | void luaT_init (lua_State *L) { | 38 | void luaT_init (lua_State *L) { |
39 | static const char *const luaT_eventname[] = { /* ORDER TM */ | 39 | static const char *const luaT_eventname[] = { /* ORDER TM */ |
40 | "__index", "__newindex", | 40 | "__index", "__newindex", |
41 | "__undef", "__isdef", | ||
41 | "__gc", "__mode", "__len", "__eq", | 42 | "__gc", "__mode", "__len", "__eq", |
42 | "__add", "__sub", "__mul", "__mod", "__pow", | 43 | "__add", "__sub", "__mul", "__mod", "__pow", |
43 | "__div", "__idiv", | 44 | "__div", "__idiv", |
@@ -248,3 +249,31 @@ void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) { | |||
248 | for (; i < wanted; i++) /* complete required results with nil */ | 249 | for (; i < wanted; i++) /* complete required results with nil */ |
249 | setnilvalue(s2v(where + i)); | 250 | setnilvalue(s2v(where + i)); |
250 | } | 251 | } |
252 | |||
253 | |||
254 | int luaT_keydef (lua_State *L, TValue *obj, TValue *key, int remove) { | ||
255 | const TValue *tm; | ||
256 | TMS event = remove ? TM_UNDEF : TM_ISDEF; | ||
257 | if (!ttistable(obj)) { /* not a table? */ | ||
258 | tm = luaT_gettmbyobj(L, obj, event); /* get its metamethod */ | ||
259 | if (notm(tm)) { /* no metamethod? */ | ||
260 | const char *msg = remove ? "remove key from" : "check key from"; | ||
261 | luaG_typeerror(L, obj, msg); /* error */ | ||
262 | } | ||
263 | /* else will call metamethod 'tm' */ | ||
264 | } | ||
265 | else { /* 'obj' is a table */ | ||
266 | Table *t = hvalue(obj); | ||
267 | tm = fasttm(L, t->metatable, event); | ||
268 | if (tm == NULL) { /* no metamethod? */ | ||
269 | const TValue *val = luaH_get(t, key); /* get entry */ | ||
270 | int res = !isempty(val); /* true if entry is not empty */ | ||
271 | if (remove && res) /* key is present and should be removed? */ | ||
272 | setempty(cast(TValue*, val)); /* remove it */ | ||
273 | return res; | ||
274 | } | ||
275 | /* else will call metamethod 'tm' */ | ||
276 | } | ||
277 | luaT_callTMres(L, tm, obj, key, L->top); | ||
278 | return !l_isfalse(s2v(L->top)); | ||
279 | } | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltm.h,v 2.32 2018/02/17 19:20:00 roberto Exp roberto $ | 2 | ** $Id: ltm.h,v 2.33 2018/02/23 13:13:31 roberto Exp roberto $ |
3 | ** Tag methods | 3 | ** Tag methods |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -19,6 +19,8 @@ | |||
19 | typedef enum { | 19 | typedef enum { |
20 | TM_INDEX, | 20 | TM_INDEX, |
21 | TM_NEWINDEX, | 21 | TM_NEWINDEX, |
22 | TM_UNDEF, | ||
23 | TM_ISDEF, | ||
22 | TM_GC, | 24 | TM_GC, |
23 | TM_MODE, | 25 | TM_MODE, |
24 | TM_LEN, | 26 | TM_LEN, |
@@ -89,5 +91,7 @@ LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams, | |||
89 | LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci, | 91 | LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci, |
90 | StkId where, int wanted); | 92 | StkId where, int wanted); |
91 | 93 | ||
94 | LUAI_FUNC int luaT_keydef (lua_State *L, TValue *obj, TValue *key, int remove); | ||
95 | |||
92 | 96 | ||
93 | #endif | 97 | #endif |