From: Jürg Billeter Date: Tue, 15 Jun 2010 20:38:12 +0000 (+0200) Subject: D-Bus: Support string arrays in variants X-Git-Tag: 0.9.2~46 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=de1e33e462a007ec9c2cab315badb8138afbd7bf;p=thirdparty%2Fvala.git D-Bus: Support string arrays in variants Fixes bug 602003. --- diff --git a/codegen/valadbusmodule.vala b/codegen/valadbusmodule.vala index f7b8d1f12..6fbf48c46 100644 --- a/codegen/valadbusmodule.vala +++ b/codegen/valadbusmodule.vala @@ -193,8 +193,12 @@ public class Vala.DBusModule : GAsyncModule { } else { return new CCodeMemberAccess (ma.inner, "%s_length%d".printf (ma.member_name, dim)); } + } else { + // must be NULL-terminated + var len_call = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length")); + len_call.add_argument (expr); + return len_call; } - return null; } CCodeExpression? generate_enum_value_from_string (CCodeFragment fragment, EnumValueType type, CCodeExpression? expr) { @@ -474,6 +478,41 @@ public class Vala.DBusModule : GAsyncModule { clastif = cif; } + // handle string arrays + var type_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_get_arg_type")); + type_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name))); + var type_check = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, type_call, new CCodeIdentifier ("DBUS_TYPE_ARRAY")); + + type_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_get_element_type")); + type_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name))); + var element_type_check = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, type_call, new CCodeIdentifier ("DBUS_TYPE_STRING")); + + type_check = new CCodeBinaryExpression (CCodeBinaryOperator.AND, type_check, element_type_check); + + var type_block = new CCodeBlock (); + var type_fragment = new CCodeFragment (); + type_block.add_statement (type_fragment); + var result = read_array (type_fragment, new ArrayType (string_type, 1, null), new CCodeIdentifier (subiter_name), null); + + var value_init = new CCodeFunctionCall (new CCodeIdentifier ("g_value_init")); + value_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_name))); + value_init.add_argument (new CCodeIdentifier ("G_TYPE_STRV")); + type_fragment.append (new CCodeExpressionStatement (value_init)); + + var value_set = new CCodeFunctionCall (new CCodeIdentifier ("g_value_take_boxed")); + value_set.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_name))); + value_set.add_argument (result); + type_fragment.append (new CCodeExpressionStatement (value_set)); + + var cif = new CCodeIfStatement (type_check, type_block); + if (clastif == null) { + fragment.append (cif); + } else { + clastif.false_statement = cif; + } + + clastif = cif; + return new CCodeIdentifier (temp_name); } @@ -802,6 +841,41 @@ public class Vala.DBusModule : GAsyncModule { clastif = cif; } + + // handle string arrays + var type_call = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE")); + type_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, expr)); + var type_check = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, type_call, new CCodeIdentifier ("G_TYPE_STRV")); + + var type_block = new CCodeBlock (); + var type_fragment = new CCodeFragment (); + type_block.add_statement (type_fragment); + + var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, iter_expr)); + iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_VARIANT")); + iter_call.add_argument (new CCodeConstant ("\"as\"")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name))); + type_fragment.append (new CCodeExpressionStatement (iter_call)); + + var value_get = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_boxed")); + value_get.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, expr)); + + write_array (type_fragment, new ArrayType (string_type, 1, null), new CCodeIdentifier (subiter_name), value_get); + + iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, iter_expr)); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name))); + type_fragment.append (new CCodeExpressionStatement (iter_call)); + + var cif = new CCodeIfStatement (type_check, type_block); + if (clastif == null) { + fragment.append (cif); + } else { + clastif.false_statement = cif; + } + + clastif = cif; } void write_hash_table (CCodeFragment fragment, ObjectType type, CCodeExpression iter_expr, CCodeExpression hash_table_expr) { diff --git a/tests/Makefile.am b/tests/Makefile.am index 929be7a3d..1ed895026 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -87,6 +87,7 @@ TESTS = \ dbus/async.test \ dbus/signals.test \ dbus/bug596862.vala \ + dbus/bug602003.test \ $(NULL) check-TESTS: $(TESTS) diff --git a/tests/dbus/bug602003.test b/tests/dbus/bug602003.test new file mode 100644 index 000000000..cf3127f42 --- /dev/null +++ b/tests/dbus/bug602003.test @@ -0,0 +1,58 @@ +Packages: dbus-glib-1 + +Program: client + +[DBus (name = "org.example.Test")] +interface Test : Object { + public abstract Value test_string () throws DBus.Error; +} + +void main () { + var conn = DBus.Bus.get (DBus.BusType.SESSION); + + // client + var test = (Test) conn.get_object ("org.example.Test", "/org/example/test"); + + Value v = test.test_string (); + string[] s = (string[]) v; + assert (s.length == 1 && s[0] == "hello"); +} + +Program: server + +[DBus (name = "org.example.Test")] +class Test : Object { + public Value test_string () { + string[] s = { "hello" }; + return s; + } +} + +MainLoop main_loop; + +void client_exit (Pid pid, int status) { + // client finished, terminate server + assert (status == 0); + main_loop.quit (); +} + +void main () { + var conn = DBus.Bus.get (DBus.BusType.SESSION); + dynamic DBus.Object bus = conn.get_object ("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus"); + + // try to register service in session bus + uint request_name_result = bus.request_name ("org.example.Test", (uint) 0); + assert (request_name_result == DBus.RequestNameReply.PRIMARY_OWNER); + + // start server + var server = new Test (); + conn.register_object ("/org/example/test", server); + + // server ready, spawn client + Pid client_pid; + Process.spawn_async (null, { "test", "/dbus/bug602003/client" }, null, SpawnFlags.DO_NOT_REAP_CHILD, null, out client_pid); + ChildWatch.add (client_pid, client_exit); + + main_loop = new MainLoop (null, false); + main_loop.run (); +}