]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
D-Bus: Support string arrays in variants
authorJürg Billeter <j@bitron.ch>
Tue, 15 Jun 2010 20:38:12 +0000 (22:38 +0200)
committerJürg Billeter <j@bitron.ch>
Tue, 15 Jun 2010 20:38:12 +0000 (22:38 +0200)
Fixes bug 602003.

codegen/valadbusmodule.vala
tests/Makefile.am
tests/dbus/bug602003.test [new file with mode: 0644]

index f7b8d1f124f22b0e6e9954bea24e290e2a154abf..6fbf48c46ef6a446b690ba53f0e03ccecaff8528 100644 (file)
@@ -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) {
index 929be7a3d1fd2ee41d7bc487700f4fcae4a15c6b..1ed895026fd69192b1c9b463646785a6f5c096d3 100644 (file)
@@ -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 (file)
index 0000000..cf3127f
--- /dev/null
@@ -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 ();
+}