diff options
author | Přemysl Janouch <p.janouch@gmail.com> | 2016-01-04 22:59:59 +0100 |
---|---|---|
committer | Přemysl Janouch <p.janouch@gmail.com> | 2016-01-04 23:14:38 +0100 |
commit | e9b39a1ef74f9a3b15de54896ae612637ddc3956 (patch) | |
tree | a8eaa847d2963083fcd7af2b66d466a83394c866 | |
parent | a227060383b4c61dd54cffba16ef26f1757e004b (diff) | |
download | xK-e9b39a1ef74f9a3b15de54896ae612637ddc3956.tar.gz xK-e9b39a1ef74f9a3b15de54896ae612637ddc3956.tar.xz xK-e9b39a1ef74f9a3b15de54896ae612637ddc3956.zip |
degesch: Lua: allow arbitrary userdata properties
-rw-r--r-- | degesch.c | 37 |
1 files changed, 35 insertions, 2 deletions
@@ -8173,8 +8173,38 @@ lua_plugin_property_get (lua_State *L) return 1; } - return luaL_error (L, "%s: %s", - "no such method or property", property_name); + // Or we look for a property set by the user (__gc cannot be overriden) + if (lua_getuservalue (L, 1) != LUA_TTABLE) + lua_pushnil (L); + else + lua_getfield (L, -1, property_name); + return 1; +} + +static int +lua_plugin_property_set (lua_State *L) +{ + luaL_checktype (L, 1, LUA_TUSERDATA); + const char *property_name = luaL_checkstring (L, 2); + luaL_checkany (L, 3); + + // We use the associated value to store user-defined properties + int type = lua_getuservalue (L, 1); + if (type == LUA_TNIL) + { + lua_pop (L, 1); + lua_newtable (L); + lua_pushvalue (L, -1); + lua_setuservalue (L, 1); + } + else if (type != LUA_TTABLE) + return luaL_error (L, "associated value is not a table"); + + // Beware that we do not check for conflicts here; + // if Lua code writes a conflicting field, it is effectively ignored + lua_pushvalue (L, 3); + lua_setfield (L, -2, property_name); + return 0; } static void @@ -8186,6 +8216,9 @@ lua_plugin_create_meta (lua_State *L, const char *name, luaL_Reg *fns) // Emulate properties for convenience lua_pushcfunction (L, lua_plugin_property_get); lua_setfield (L, -2, "__index"); + lua_pushcfunction (L, lua_plugin_property_set); + lua_setfield (L, -2, "__newindex"); + lua_pop (L, 1); } |