diff --git a/lib/wplua/value.c b/lib/wplua/value.c index 52f9015fd336cbef693b9c813c322822b55987b2..87a29986f64fc892eb37fc394b8fbf67f510ddd4 100644 --- a/lib/wplua/value.c +++ b/lib/wplua/value.c @@ -15,9 +15,10 @@ wplua_table_to_properties (lua_State *L, int idx) { WpProperties *p = wp_properties_new_empty (); const gchar *key, *value; + int table = lua_absindex (L, idx); lua_pushnil(L); - while (lua_next (L, idx) != 0) { + while (lua_next (L, table) != 0) { /* copy key & value to convert them to string */ lua_pushvalue (L, -2); key = lua_tostring (L, -1); @@ -49,6 +50,104 @@ wplua_properties_to_table (lua_State *L, WpProperties *p) } } +GVariant * +wplua_table_to_asv (lua_State *L, int idx) +{ + g_auto (GVariantBuilder) b = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_VARDICT); + int table = lua_absindex (L, idx); + + lua_pushnil (L); + while (lua_next (L, table)) { + /* each argument must have a string as key */ + if (lua_type (L, -2) != LUA_TSTRING) { + wp_warning ("skipping non-string key"); + lua_pop (L, 1); + continue; /* skip, it's probably harmless */ + } + + const char *key = lua_tostring (L, -2); + + switch (lua_type (L, -1)) { + case LUA_TBOOLEAN: + g_variant_builder_add (&b, "{sv}", key, + g_variant_new_boolean (lua_toboolean (L, -1))); + break; + + case LUA_TNUMBER: + if (lua_isinteger (L, -1)) { + g_variant_builder_add (&b, "{sv}", key, + g_variant_new_int64 (lua_tointeger (L, -1))); + } else { + g_variant_builder_add (&b, "{sv}", key, + g_variant_new_double (lua_tonumber (L, -1))); + } + break; + + case LUA_TSTRING: + g_variant_builder_add (&b, "{sv}", key, + g_variant_new_string (lua_tostring (L, -1))); + break; + + case LUA_TTABLE: + g_variant_builder_add (&b, "{sv}", key, wplua_table_to_asv (L, -1)); + break; + + default: + wp_warning ("skipping bad value (its type cannot be represented in GVariant)"); + break; + } + + lua_pop (L, 1); + } + + return g_variant_builder_end (&b); +} + +void +wplua_asv_to_table (lua_State *L, GVariant *asv) +{ + lua_newtable (L); + if (asv) { + GVariantIter iter; + g_variant_iter_init (&iter, asv); + const gchar *key; + GVariant *value; + + while (g_variant_iter_loop (&iter, "{&sv}", &key, &value)) { + lua_pushstring (L, key); + + if (g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN)) { + lua_pushboolean (L, g_variant_get_boolean (value)); + } + else if (g_variant_is_of_type (value, G_VARIANT_TYPE_INT16)) { + lua_pushinteger (L, g_variant_get_int16 (value)); + } + else if (g_variant_is_of_type (value, G_VARIANT_TYPE_INT32)) { + lua_pushinteger (L, g_variant_get_int32 (value)); + } + else if (g_variant_is_of_type (value, G_VARIANT_TYPE_INT64)) { + lua_pushinteger (L, g_variant_get_int64 (value)); + } + else if (g_variant_is_of_type (value, G_VARIANT_TYPE_DOUBLE)) { + lua_pushnumber (L, g_variant_get_double (value)); + } + else if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) { + lua_pushstring (L, g_variant_get_string (value, NULL)); + } + else if (g_variant_is_of_type (value, G_VARIANT_TYPE_VARDICT)) { + wplua_asv_to_table (L, value); + } + else { + wp_warning ("skipping bad value (its type cannot be represented in lua)"); + lua_pop (L, 1); + continue; + } + + lua_settable (L, -3); + } + } +} + void wplua_lua_to_gvalue (lua_State *L, int idx, GValue *v) { @@ -121,6 +220,10 @@ wplua_lua_to_gvalue (lua_State *L, int idx, GValue *v) case G_TYPE_FLAGS: g_value_set_flags (v, lua_tointeger (L, idx)); break; + case G_TYPE_VARIANT: + if (lua_istable (L, idx)) + g_value_set_variant (v, wplua_table_to_asv (L, idx)); + break; default: break; } @@ -197,9 +300,16 @@ wplua_gvalue_to_lua (lua_State *L, const GValue *v) lua_pushstring (L, pspec->name); break; } - case G_TYPE_VARIANT: + case G_TYPE_VARIANT: { + GVariant *asv = g_value_get_variant (v); + if (g_variant_is_of_type (asv, G_VARIANT_TYPE_VARDICT)) + wplua_asv_to_table (L, asv); + else + /* FIXME maybe implement if needed */ + lua_pushnil (L); + break; + } default: - /* FIXME implement */ lua_pushnil (L); break; } diff --git a/lib/wplua/wplua.h b/lib/wplua/wplua.h index 502932d1940d4423de799504a590f9c4fc115a89..1874a140b710753791ff1ff0d5998f5c517c7397 100644 --- a/lib/wplua/wplua.h +++ b/lib/wplua/wplua.h @@ -72,6 +72,9 @@ int wplua_gvalue_to_lua (lua_State *L, const GValue *v); WpProperties * wplua_table_to_properties (lua_State *L, int idx); void wplua_properties_to_table (lua_State *L, WpProperties *p); +GVariant * wplua_table_to_asv (lua_State *L, int idx); +void wplua_asv_to_table (lua_State *L, GVariant *p); + gboolean wplua_load_buffer (lua_State * L, const gchar *buf, gsize size, GError **error); gboolean wplua_load_uri (lua_State * L, const gchar *uri, GError **error); diff --git a/tests/wplua/wplua.c b/tests/wplua/wplua.c index a36967cd1f32df917d52049d7b9849606b250409..49589a1fe4dce0074efa8be6090d9d06ec8cd1ea 100644 --- a/tests/wplua/wplua.c +++ b/tests/wplua/wplua.c @@ -502,6 +502,62 @@ test_wplua_sandbox_config () wplua_free (L); } +static void +test_wplua_convert_asv () +{ + g_autoptr (GError) error = NULL; + lua_State *L = wplua_new (); + + g_autoptr (GVariant) v = g_variant_new_parsed ("@a{sv} { " + "'test-int': <42>, " + "'test-double': <3.14>, " + "'test-string': <'foobar'>, " + "'test-boolean': <true>, " + "'nested-table': <@a{sv} { 'string': <'baz'> }> " + "}"); + wplua_asv_to_table (L, v); + lua_setglobal (L, "o"); + + const gchar code2[] = + "assert (o['test-string'] == 'foobar')\n" + "assert (o['test-int'] == 42)\n" + "assert (math.abs (o['test-double'] - 3.14) < 0.0000000001)\n" + "assert (o['test-boolean'] == true)\n" + "assert (o['nested-table']['string'] == 'baz')\n"; + wplua_load_buffer (L, code2, sizeof (code2) - 1, &error); + g_assert_no_error (error); + + lua_getglobal (L, "o"); + g_autoptr (GVariant) fromlua = wplua_table_to_asv (L, -1); + + gint64 test_int = 0; + g_assert_true (g_variant_lookup (fromlua, "test-int", "x", &test_int)); + g_assert_cmpint (test_int, ==, 42); + + gdouble test_double = 0; + g_assert_true (g_variant_lookup (fromlua, "test-double", "d", &test_double)); + g_assert_cmpfloat_with_epsilon (test_double, 3.14, 0.0000000001); + + const gchar *test_str = NULL; + g_assert_true (g_variant_lookup (fromlua, "test-string", "&s", &test_str)); + g_assert_cmpstr (test_str, ==, "foobar"); + + gboolean test_boolean = FALSE; + g_assert_true (g_variant_lookup (fromlua, "test-boolean", "b", &test_boolean)); + g_assert_true (test_boolean); + + g_autoptr (GVariant) nested = NULL; + g_assert_true (g_variant_lookup (fromlua, "nested-table", "@a{sv}", &nested)); + g_assert_nonnull (nested); + g_assert_true (g_variant_is_of_type (nested, G_VARIANT_TYPE_VARDICT)); + + test_str = NULL; + g_assert_true (g_variant_lookup (nested, "string", "&s", &test_str)); + g_assert_cmpstr (test_str, ==, "baz"); + + wplua_free (L); +} + gint main (gint argc, gchar *argv[]) { @@ -515,6 +571,7 @@ main (gint argc, gchar *argv[]) g_test_add_func ("/wplua/signals", test_wplua_signals); g_test_add_func ("/wplua/sandbox/script", test_wplua_sandbox_script); g_test_add_func ("/wplua/sandbox/config", test_wplua_sandbox_config); + g_test_add_func ("/wplua/convert/asv", test_wplua_convert_asv); return g_test_run (); }