wplua: improve gvariant <-> lua conversion functions

* Add more generic lua -> gvariant conversion
* Cleanup the gvariant -> lua function and rename it
This commit is contained in:
George Kiagiadakis
2021-02-13 12:42:36 +02:00
parent 413ff73bab
commit dacf19d9c7
5 changed files with 106 additions and 139 deletions

View File

@@ -51,56 +51,106 @@ wplua_properties_to_table (lua_State *L, WpProperties *p)
} }
GVariant * GVariant *
wplua_table_to_asv (lua_State *L, int idx) wplua_lua_to_gvariant (lua_State *L, int idx)
{ {
g_auto (GVariantBuilder) b = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_VARDICT); switch (lua_type (L, idx)) {
int table = lua_absindex (L, idx); case LUA_TNIL:
return g_variant_new ("()");
case LUA_TBOOLEAN:
return g_variant_new_boolean (lua_toboolean (L, idx));
case LUA_TNUMBER:
if (lua_isinteger (L, idx))
return g_variant_new_int64 (lua_tointeger (L, idx));
else
return g_variant_new_double (lua_tonumber (L, idx));
case LUA_TSTRING:
return g_variant_new_string (lua_tostring (L, idx));
case LUA_TTABLE: {
GVariantBuilder b = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_VARDICT);
const gchar *key;
int table = lua_absindex (L, idx);
lua_pushnil (L); lua_pushnil (L);
while (lua_next (L, table)) { while (lua_next (L, table) != 0) {
/* each argument must have a string as key */ /* copy key to convert it to string */
if (lua_type (L, -2) != LUA_TSTRING) { lua_pushvalue (L, -2);
wp_warning ("skipping non-string key"); key = lua_tostring (L, -1);
lua_pop (L, 1); g_variant_builder_add (&b, "{sv}", key, wplua_lua_to_gvariant (L, -2));
continue; /* skip, it's probably harmless */ lua_pop (L, 2);
} }
return g_variant_builder_end (&b);
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);
} }
default:
wp_warning ("skipping bad value (its type cannot be represented in GVariant)");
return NULL;
}
}
return g_variant_builder_end (&b); void
wplua_gvariant_to_lua (lua_State *L, GVariant *variant)
{
if (variant == NULL || g_variant_is_of_type (variant, G_VARIANT_TYPE_UNIT)) {
lua_pushnil (L);
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT16)) {
lua_pushinteger (L, g_variant_get_int16 (variant));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT32)) {
lua_pushinteger (L, g_variant_get_int32 (variant));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT64)) {
lua_pushinteger (L, g_variant_get_int64 (variant));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT16)) {
lua_pushinteger (L, g_variant_get_uint16 (variant));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32)) {
lua_pushinteger (L, g_variant_get_uint32 (variant));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT64)) {
lua_pushinteger (L, g_variant_get_uint64 (variant));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_DOUBLE)) {
lua_pushnumber (L, g_variant_get_double (variant));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN)) {
lua_pushboolean (L, g_variant_get_boolean (variant));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) {
lua_pushstring (L, g_variant_get_string (variant, NULL));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARIANT)) {
wplua_gvariant_to_lua (L, g_variant_get_variant (variant));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_DICTIONARY)) {
gsize n_children, i;
n_children = g_variant_n_children (variant);
lua_createtable (L, 0, n_children);
for (i = 0; i < n_children; i++) {
g_autoptr (GVariant) key, value;
g_variant_get_child (variant, i, "{@?@*}", &key, &value);
wplua_gvariant_to_lua (L, key);
wplua_gvariant_to_lua (L, value);
lua_settable (L, -3);
}
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE ("a?"))) {
gsize n_children, i;
n_children = g_variant_n_children (variant);
lua_createtable (L, n_children, 0);
for (i = 0; i < n_children; i++) {
g_autoptr (GVariant) value;
value = g_variant_get_child_value (variant, i);
wplua_gvariant_to_lua (L, value);
lua_seti (L, -2, i);
}
}
else {
g_autofree gchar *type_name =
g_variant_type_dup_string (g_variant_get_type (variant));
wp_warning ("Unhandled GVariant type %s", type_name);
lua_pushnil (L);
}
} }
void void
@@ -176,96 +226,13 @@ wplua_lua_to_gvalue (lua_State *L, int idx, GValue *v)
g_value_set_flags (v, lua_tointeger (L, idx)); g_value_set_flags (v, lua_tointeger (L, idx));
break; break;
case G_TYPE_VARIANT: case G_TYPE_VARIANT:
if (lua_istable (L, idx)) g_value_set_variant (v, wplua_lua_to_gvariant (L, idx));
g_value_set_variant (v, wplua_table_to_asv (L, idx));
break; break;
default: default:
break; break;
} }
} }
void
wplua_gvariant_to_table (lua_State *L, GVariant *variant)
{
if (variant == NULL) {
lua_pushnil (L);
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT16)) {
lua_pushinteger (L, g_variant_get_int16 (variant));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT32)) {
lua_pushinteger (L, g_variant_get_int32 (variant));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT64)) {
lua_pushinteger (L, g_variant_get_int64 (variant));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT16)) {
lua_pushinteger (L, g_variant_get_uint16 (variant));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32)) {
lua_pushinteger (L, g_variant_get_uint32 (variant));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT64)) {
lua_pushinteger (L, g_variant_get_uint64 (variant));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_DOUBLE)) {
lua_pushnumber (L, g_variant_get_double (variant));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN)) {
lua_pushboolean (L, g_variant_get_boolean (variant));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) {
lua_pushstring (L, g_variant_get_string (variant, NULL));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARIANT)) {
wplua_gvariant_to_table (L, g_variant_get_variant (variant));
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_DICTIONARY)) {
gsize n_children, i;
n_children = g_variant_n_children (variant);
lua_createtable (L, 0, n_children);
for (i = 0; i < n_children; i++) {
g_autoptr (GVariant) key, value;
g_variant_get_child (variant, i, "{@?@*}", &key, &value);
wplua_gvariant_to_table (L, key);
wplua_gvariant_to_table (L, value);
lua_settable (L, -3);
}
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE ("a?"))) {
gsize n_children, i;
n_children = g_variant_n_children (variant);
lua_createtable (L, n_children, 0);
for (i = 0; i < n_children; i++) {
g_autoptr (GVariant) value;
value = g_variant_get_child_value (variant, i);
wplua_gvariant_to_table (L, value);
lua_seti (L, -2, i);
}
}
/* FIXME maybe implement if needed */
else {
g_autofree gchar *type_name =
g_variant_type_dup_string (g_variant_get_type (variant));
wp_warning ("Unhandled gvariant type %s", type_name);
lua_pushnil (L);
}
}
int int
wplua_gvalue_to_lua (lua_State *L, const GValue *v) wplua_gvalue_to_lua (lua_State *L, const GValue *v)
{ {
@@ -339,7 +306,7 @@ wplua_gvalue_to_lua (lua_State *L, const GValue *v)
} }
case G_TYPE_VARIANT: { case G_TYPE_VARIANT: {
GVariant *variant = g_value_get_variant (v); GVariant *variant = g_value_get_variant (v);
wplua_gvariant_to_table (L, variant); wplua_gvariant_to_lua (L, variant);
break; break;
} }
default: default:

View File

@@ -69,12 +69,12 @@ GClosure * wplua_function_to_closure (lua_State *L, int idx);
void wplua_lua_to_gvalue (lua_State *L, int idx, GValue *v); void wplua_lua_to_gvalue (lua_State *L, int idx, GValue *v);
int wplua_gvalue_to_lua (lua_State *L, const GValue *v); int wplua_gvalue_to_lua (lua_State *L, const GValue *v);
GVariant * wplua_lua_to_gvariant (lua_State *L, int idx);
void wplua_gvariant_to_lua (lua_State *L, GVariant *p);
WpProperties * wplua_table_to_properties (lua_State *L, int idx); WpProperties * wplua_table_to_properties (lua_State *L, int idx);
void wplua_properties_to_table (lua_State *L, WpProperties *p); void wplua_properties_to_table (lua_State *L, WpProperties *p);
GVariant * wplua_table_to_asv (lua_State *L, int idx);
void wplua_gvariant_to_table (lua_State *L, GVariant *p);
gboolean wplua_load_buffer (lua_State * L, const gchar *buf, gsize size, gboolean wplua_load_buffer (lua_State * L, const gchar *buf, gsize size,
int nargs, int nres, GError **error); int nargs, int nres, GError **error);
gboolean wplua_load_uri (lua_State * L, const gchar *uri, int nargs, int nres, gboolean wplua_load_uri (lua_State * L, const gchar *uri, int nargs, int nres,

View File

@@ -41,7 +41,7 @@ execute_script (lua_State *L, struct ScriptData * s, GError ** error)
{ {
int nargs = 0; int nargs = 0;
if (s->args) { if (s->args) {
wplua_gvariant_to_table (L, s->args); wplua_gvariant_to_lua (L, s->args);
nargs++; nargs++;
} }
return wplua_load_path (L, s->filename, nargs, 0, error); return wplua_load_path (L, s->filename, nargs, 0, error);

View File

@@ -109,7 +109,7 @@ load_components (lua_State *L, WpCore * core, GError ** error)
/* optional component arguments */ /* optional component arguments */
GVariant *args = NULL; GVariant *args = NULL;
if (lua_getfield (L, table, "args") == LUA_TTABLE) { if (lua_getfield (L, table, "args") == LUA_TTABLE) {
args = wplua_table_to_asv (L, -1); args = wplua_lua_to_gvariant (L, -1);
} }
wp_debug ("load component: %s (%s)", component, type); wp_debug ("load component: %s (%s)", component, type);

View File

@@ -515,7 +515,7 @@ test_wplua_convert_asv ()
"'test-boolean': <true>, " "'test-boolean': <true>, "
"'nested-table': <@a{sv} { 'string': <'baz'> }> " "'nested-table': <@a{sv} { 'string': <'baz'> }> "
"}"); "}");
wplua_gvariant_to_table (L, v); wplua_gvariant_to_lua (L, v);
lua_setglobal (L, "o"); lua_setglobal (L, "o");
const gchar code2[] = const gchar code2[] =
@@ -528,7 +528,7 @@ test_wplua_convert_asv ()
g_assert_no_error (error); g_assert_no_error (error);
lua_getglobal (L, "o"); lua_getglobal (L, "o");
g_autoptr (GVariant) fromlua = wplua_table_to_asv (L, -1); g_autoptr (GVariant) fromlua = wplua_lua_to_gvariant (L, -1);
gint64 test_int = 0; gint64 test_int = 0;
g_assert_true (g_variant_lookup (fromlua, "test-int", "x", &test_int)); g_assert_true (g_variant_lookup (fromlua, "test-int", "x", &test_int));
@@ -571,7 +571,7 @@ test_wplua_script_arguments ()
"'test-boolean': <true>, " "'test-boolean': <true>, "
"'nested-table': <@a{sv} { 'string': <'baz'> }> " "'nested-table': <@a{sv} { 'string': <'baz'> }> "
"}"); "}");
wplua_gvariant_to_table (L, v); wplua_gvariant_to_lua (L, v);
const gchar code2[] = const gchar code2[] =
"local o = ...\n" "local o = ...\n"
@@ -585,7 +585,7 @@ test_wplua_script_arguments ()
/* same test, but with sandbox enabled */ /* same test, but with sandbox enabled */
wplua_enable_sandbox (L, WP_LUA_SANDBOX_ISOLATE_ENV); wplua_enable_sandbox (L, WP_LUA_SANDBOX_ISOLATE_ENV);
wplua_gvariant_to_table (L, v); wplua_gvariant_to_lua (L, v);
wplua_load_buffer (L, code2, sizeof (code2) - 1, 1, 0, &error); wplua_load_buffer (L, code2, sizeof (code2) - 1, 1, 0, &error);
g_assert_no_error (error); g_assert_no_error (error);