[grilo-plugins] lua-factory: Create a proxy for grl and grl.lua
- From: Bastien Nocera <hadess src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [grilo-plugins] lua-factory: Create a proxy for grl and grl.lua
- Date: Mon, 21 Mar 2016 22:56:10 +0000 (UTC)
commit 7c9315e7bb7bf7c572663e002c321d53d76d25cf
Author: Victor Toso <me victortoso com>
Date: Fri Mar 4 16:30:50 2016 +0100
lua-factory: Create a proxy for grl and grl.lua
By creating a proxy table with custom metatable in order to have more
control into changes make in grl and grl.lua by Lua sources.
At the moment, the proxy redirects read access (__index metamethod)
and write access (__newindex metamethod) to the original table but later
on we can remove write access from Lua sources to our library.
Internally we are should be using the __call metamethod in order to
retrieve the original table.
https://bugzilla.gnome.org/show_bug.cgi?id=763046
src/lua-factory/grl-lua-common.h | 1 +
src/lua-factory/grl-lua-library-operations.c | 100 ++++++++++++++++++++++++++
src/lua-factory/grl-lua-library.c | 5 ++
3 files changed, 106 insertions(+), 0 deletions(-)
---
diff --git a/src/lua-factory/grl-lua-common.h b/src/lua-factory/grl-lua-common.h
index fa5c12e..405e41e 100644
--- a/src/lua-factory/grl-lua-common.h
+++ b/src/lua-factory/grl-lua-common.h
@@ -87,6 +87,7 @@ void grl_lua_library_push_grl_options (lua_State *L, guint operation_id, GrlOper
void grl_lua_library_push_grl_callback (lua_State *L, OperationSpec *os);
/* grl-lua-library-operations */
+void grl_lua_operations_set_proxy_table (lua_State *L, gint index);
gboolean grl_lua_operations_pcall (lua_State *L, gint nargs, OperationSpec *os, GError **err);
#endif /* _GRL_LUA_LIBRARY_COMMON_H_ */
diff --git a/src/lua-factory/grl-lua-library-operations.c b/src/lua-factory/grl-lua-library-operations.c
index 031b624..0074990 100644
--- a/src/lua-factory/grl-lua-library-operations.c
+++ b/src/lua-factory/grl-lua-library-operations.c
@@ -24,10 +24,110 @@
#include "grl-lua-common.h"
/* =========================================================================
+ * Internal functions ======================================================
+ * ========================================================================= */
+
+/* ============== Proxy related ============================================ */
+
+/*
+ * Get the original table from proxy which is still able to rw operations
+ *
+ * @index: position to the proxy table in the stack
+ * return: the original table in top of the stack
+ *
+ */
+static void
+proxy_table_get_rw (lua_State *L,
+ guint index)
+{
+ gint *table_ref;
+
+ /* using table as function */
+ lua_pushvalue (L, index);
+ table_ref = lua_newuserdata (L, sizeof (gint));
+ *table_ref = 0;
+ if (lua_pcall (L, 1, 0, 0)) {
+ GRL_WARNING ("Failed to get rw table due: %s",
+ lua_tolstring (L, -1, NULL));
+ lua_pop (L, 1);
+ }
+ lua_rawgeti (L, LUA_REGISTRYINDEX, *table_ref);
+ luaL_unref (L, LUA_REGISTRYINDEX, *table_ref);
+}
+
+/*
+ * proxy handler for __call metamethod; This metamethod is called when using
+ * the table as a function (e.g {}()). The proxy uses this metamethod in order
+ * to retrieve a reference to original table which is still capabable of
+ * read-write operations.
+ *
+ * @userdata: Expects pointer to integer which will hold the reference to the
+ * requested table.
+ */
+static int
+proxy_metatable_handle_call (lua_State *L)
+{
+ luaL_argcheck (L, lua_istable (L, 1), 1, "First argument is always itself");
+ luaL_argcheck (L, lua_isuserdata (L, 2), 2,
+ "expecting userdata as reference holder (gint *)");
+ gint *table_ref = lua_touserdata (L, 2);
+ lua_pushvalue (L, lua_upvalueindex (1));
+ *table_ref = luaL_ref (L, LUA_REGISTRYINDEX);
+ return 0;
+}
+
+/* =========================================================================
* Exported functions ======================================================
* ========================================================================= */
/*
+ * Create a read-only proxy table which will only be allowed to access the
+ * original table.
+ *
+ * @index: position to the table in the stack
+ * return: switch the table at @index with a read-only proxy
+ */
+void
+grl_lua_operations_set_proxy_table (lua_State *L,
+ gint index)
+{
+ g_assert_true (lua_istable (L, index));
+
+ /* Proxy table that will be switched with the one at index */
+ lua_newtable (L);
+
+ /* Metatable */
+ lua_createtable (L, 0, 3);
+
+ /* __index: triggered when acessing a value of given table */
+ lua_pushstring (L, "__index");
+ lua_pushvalue (L, index - 3);
+ lua_settable (L, -3);
+
+ /* __len: triggered when counting the length of given table */
+ lua_pushstring (L, "__len");
+ lua_pushvalue (L, index - 3);
+ lua_settable (L, -3);
+
+ /* __newindex: triggered when inserting new key/value to given table */
+ lua_pushstring (L, "__newindex");
+ lua_pushvalue (L, index - 3);
+ lua_settable (L, -3);
+
+ /* __call: triggered when using the table as a function */
+ lua_pushstring (L, "__call");
+ lua_pushvalue (L, index - 3);
+ lua_pushcclosure (L, proxy_metatable_handle_call, 1);
+ lua_settable (L, -3);
+
+ /* Set metatable to our proxy */
+ lua_setmetatable (L, -2);
+
+ /* Replace original table with our proxy */
+ lua_replace (L, index - 1);
+}
+
+/*
* This is a wrapper to do execute the lua_pcall and all internals that might
* be necessary to Lua-Library before calling the Lua function. The stack
* requirements are the same of lua_pcall, function and arguments in expected
diff --git a/src/lua-factory/grl-lua-library.c b/src/lua-factory/grl-lua-library.c
index 9b66da8..7b4fe9a 100644
--- a/src/lua-factory/grl-lua-library.c
+++ b/src/lua-factory/grl-lua-library.c
@@ -1438,8 +1438,13 @@ luaopen_grilo (lua_State *L)
}
lua_pop (L, 1);
+ grl_lua_operations_set_proxy_table (L, -1);
+
/* Those modules are called in 'lua' table, inside 'grl' */
lua_settable (L, -3);
+
+ grl_lua_operations_set_proxy_table (L, -1);
+
return 1;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]