3 * Copyright (C) 2008-2009 Jürg Billeter
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Jürg Billeter <j@bitron.ch>
23 internal class Vala
.DBusModule
: GAsyncModule
{
24 struct BasicTypeInfo
{
25 public weak string signature
;
26 public weak string type_name
;
27 public weak string cname
;
28 public weak string gtype
;
29 public weak string? get_value_function
;
30 public weak string set_value_function
;
33 const BasicTypeInfo
[] basic_types
= {
34 { "y", "BYTE", "guint8", "G_TYPE_UCHAR", "g_value_get_uchar", "g_value_set_uchar" },
35 { "b", "BOOLEAN", "dbus_bool_t", "G_TYPE_BOOLEAN", "g_value_get_boolean", "g_value_set_boolean" },
36 { "n", "INT16", "dbus_int16_t", "G_TYPE_INT", null, "g_value_set_int" },
37 { "q", "UINT16", "dbus_uint16_t", "G_TYPE_UINT", null, "g_value_set_uint" },
38 { "i", "INT32", "dbus_int32_t", "G_TYPE_INT", "g_value_get_int", "g_value_set_int" },
39 { "u", "UINT32", "dbus_uint32_t", "G_TYPE_UINT", "g_value_get_uint", "g_value_set_uint" },
40 { "x", "INT64", "dbus_int64_t", "G_TYPE_INT64", "g_value_get_int64", "g_value_set_int64" },
41 { "t", "UINT64", "dbus_uint64_t", "G_TYPE_UINT64", "g_value_get_uint64", "g_value_set_uint64" },
42 { "d", "DOUBLE", "double", "G_TYPE_DOUBLE", "g_value_get_double", "g_value_set_double" },
43 { "s", "STRING", "const char*", "G_TYPE_STRING", "g_value_get_string", "g_value_take_string" },
44 { "o", "OBJECT_PATH", "const char*", "G_TYPE_STRING", null, "g_value_take_string" },
45 { "g", "SIGNATURE", "const char*", "G_TYPE_STRING", null, "g_value_take_string" }
48 public DBusModule (CCodeGenerator codegen
, CCodeModule? next
) {
52 public string?
get_dbus_name (TypeSymbol symbol
) {
53 var dbus
= symbol
.get_attribute ("DBus");
58 return dbus
.get_string ("name");
61 bool get_basic_type_info (string signature
, out BasicTypeInfo basic_type
) {
62 foreach (BasicTypeInfo info
in basic_types
) {
63 if (info
.signature
== signature
) {
71 public static string get_type_signature (DataType datatype
) {
72 return datatype
.get_type_signature ();
75 CCodeExpression?
get_array_length (CCodeExpression expr
, int dim
) {
76 var id
= expr as CCodeIdentifier
;
77 var ma
= expr as CCodeMemberAccess
;
79 return new
CCodeIdentifier ("%s_length%d".printf (id
.name
, dim
));
80 } else if (ma
!= null) {
81 return new CCodeMemberAccess
.pointer (ma
.inner
, "%s_length%d".printf (ma
.member_name
, dim
));
86 CCodeExpression
read_basic (CCodeFragment fragment
, BasicTypeInfo basic_type
, CCodeExpression iter_expr
) {
87 string temp_name
= "_tmp%d_".printf (next_temp_var_id
++);
89 var cdecl
= new
CCodeDeclaration (basic_type
.cname
);
90 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
));
91 fragment
.append (cdecl
);
93 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_get_basic"));
94 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
95 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (temp_name
)));
96 fragment
.append (new
CCodeExpressionStatement (iter_call
));
98 var temp_result
= new
CCodeIdentifier (temp_name
);
100 if (basic_type
.signature
== "s"
101 || basic_type
.signature
== "o"
102 || basic_type
.signature
== "g") {
103 var dup_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strdup"));
104 dup_call
.add_argument (temp_result
);
111 CCodeExpression
read_array (CCodeFragment fragment
, ArrayType array_type
, CCodeExpression iter_expr
, CCodeExpression? expr
) {
112 string temp_name
= "_tmp%d_".printf (next_temp_var_id
++);
114 var new_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_new"));
115 new_call
.add_argument (new
CCodeIdentifier (array_type
.element_type
.get_cname ()));
116 // add one extra element for NULL-termination
117 new_call
.add_argument (new
CCodeConstant ("5"));
119 var cdecl
= new
CCodeDeclaration (array_type
.get_cname ());
120 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
, new_call
));
121 fragment
.append (cdecl
);
123 cdecl
= new
CCodeDeclaration ("int");
124 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
+ "_length", new
CCodeConstant ("0")));
125 fragment
.append (cdecl
);
127 cdecl
= new
CCodeDeclaration ("int");
128 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
+ "_size", new
CCodeConstant ("4")));
129 fragment
.append (cdecl
);
131 read_array_dim (fragment
, array_type
, 1, temp_name
, iter_expr
, expr
);
133 if (array_type
.element_type
.is_reference_type_or_type_parameter ()) {
134 // NULL terminate array
135 var length
= new
CCodeIdentifier (temp_name
+ "_length");
136 var element_access
= new
CCodeElementAccess (new
CCodeIdentifier (temp_name
), length
);
137 fragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (element_access
, new
CCodeIdentifier ("NULL"))));
140 return new
CCodeIdentifier (temp_name
);
143 void read_array_dim (CCodeFragment fragment
, ArrayType array_type
, int dim
, string temp_name
, CCodeExpression iter_expr
, CCodeExpression? expr
) {
144 string subiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
146 var cdecl
= new
CCodeDeclaration ("int");
147 cdecl
.add_declarator (new
CCodeVariableDeclarator ("%s_length%d".printf (temp_name
, dim
), new
CCodeConstant ("0")));
148 fragment
.append (cdecl
);
150 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
151 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
152 fragment
.append (cdecl
);
154 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_recurse"));
155 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
156 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
157 fragment
.append (new
CCodeExpressionStatement (iter_call
));
159 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_get_arg_type"));
160 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
162 var cforblock
= new
CCodeBlock ();
163 var cforfragment
= new
CCodeFragment ();
164 cforblock
.add_statement (cforfragment
);
165 var cfor
= new
CCodeForStatement (iter_call
, cforblock
);
166 cfor
.add_iterator (new
CCodeUnaryExpression (CCodeUnaryOperator
.POSTFIX_INCREMENT
, new
CCodeIdentifier ("%s_length%d".printf (temp_name
, dim
))));
168 if (dim
< array_type
.rank
) {
169 read_array_dim (cforfragment
, array_type
, dim
+ 1, temp_name
, new
CCodeIdentifier (subiter_name
), expr
);
171 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_next"));
172 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
173 cforfragment
.append (new
CCodeExpressionStatement (iter_call
));
175 var size_check
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, new
CCodeIdentifier (temp_name
+ "_size"), new
CCodeIdentifier (temp_name
+ "_length"));
176 var renew_block
= new
CCodeBlock ();
178 // tmp_size = (2 * tmp_size);
179 var new_size
= new
CCodeBinaryExpression (CCodeBinaryOperator
.MUL
, new
CCodeConstant ("2"), new
CCodeIdentifier (temp_name
+ "_size"));
180 renew_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier (temp_name
+ "_size"), new_size
)));
182 var renew_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_renew"));
183 renew_call
.add_argument (new
CCodeIdentifier (array_type
.element_type
.get_cname ()));
184 renew_call
.add_argument (new
CCodeIdentifier (temp_name
));
185 // add one extra element for NULL-termination
186 renew_call
.add_argument (new
CCodeBinaryExpression (CCodeBinaryOperator
.PLUS
, new
CCodeIdentifier (temp_name
+ "_size"), new
CCodeConstant ("1")));
187 var renew_stmt
= new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier (temp_name
), renew_call
));
188 renew_block
.add_statement (renew_stmt
);
190 var cif
= new
CCodeIfStatement (size_check
, renew_block
);
191 cforfragment
.append (cif
);
193 var element_access
= new
CCodeElementAccess (new
CCodeIdentifier (temp_name
), new
CCodeUnaryExpression (CCodeUnaryOperator
.POSTFIX_INCREMENT
, new
CCodeIdentifier (temp_name
+ "_length")));
194 var element_expr
= read_expression (cforfragment
, array_type
.element_type
, new
CCodeIdentifier (subiter_name
), null);
195 cforfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (element_access
, element_expr
)));
198 fragment
.append (cfor
);
201 fragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (get_array_length (expr
, dim
), new
CCodeIdentifier ("%s_length%d".printf (temp_name
, dim
)))));
205 CCodeExpression
read_struct (CCodeFragment fragment
, Struct st
, CCodeExpression iter_expr
) {
206 string temp_name
= "_tmp%d_".printf (next_temp_var_id
++);
207 string subiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
209 var cdecl
= new
CCodeDeclaration (st
.get_cname ());
210 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
));
211 fragment
.append (cdecl
);
213 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
214 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
215 fragment
.append (cdecl
);
217 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_recurse"));
218 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
219 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
220 fragment
.append (new
CCodeExpressionStatement (iter_call
));
222 foreach (Field f
in st
.get_fields ()) {
223 if (f
.binding
!= MemberBinding
.INSTANCE
) {
227 var field_expr
= read_expression (fragment
, f
.field_type
, new
CCodeIdentifier (subiter_name
), new
CCodeMemberAccess (new
CCodeIdentifier (temp_name
), f
.get_cname ()));
228 fragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeMemberAccess (new
CCodeIdentifier (temp_name
), f
.get_cname ()), field_expr
)));
231 return new
CCodeIdentifier (temp_name
);
234 CCodeExpression
read_value (CCodeFragment fragment
, CCodeExpression iter_expr
) {
235 string temp_name
= "_tmp%d_".printf (next_temp_var_id
++);
236 string subiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
238 // 0-initialize struct with struct initializer { 0 }
239 var cvalinit
= new
CCodeInitializerList ();
240 cvalinit
.append (new
CCodeConstant ("0"));
242 var cdecl
= new
CCodeDeclaration ("GValue");
243 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
, cvalinit
));
244 fragment
.append (cdecl
);
246 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
247 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
248 fragment
.append (cdecl
);
250 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_recurse"));
251 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
252 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
253 fragment
.append (new
CCodeExpressionStatement (iter_call
));
255 CCodeIfStatement clastif
= null;
257 foreach (BasicTypeInfo basic_type
in basic_types
) {
258 var type_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_get_arg_type"));
259 type_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
260 var type_check
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, type_call
, new
CCodeIdentifier ("DBUS_TYPE_" + basic_type
.type_name
));
262 var type_block
= new
CCodeBlock ();
263 var type_fragment
= new
CCodeFragment ();
264 type_block
.add_statement (type_fragment
);
265 var result
= read_basic (type_fragment
, basic_type
, new
CCodeIdentifier (subiter_name
));
267 var value_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_init"));
268 value_init
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (temp_name
)));
269 value_init
.add_argument (new
CCodeIdentifier (basic_type
.gtype
));
270 type_fragment
.append (new
CCodeExpressionStatement (value_init
));
272 var value_set
= new
CCodeFunctionCall (new
CCodeIdentifier (basic_type
.set_value_function
));
273 value_set
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (temp_name
)));
274 value_set
.add_argument (result
);
275 type_fragment
.append (new
CCodeExpressionStatement (value_set
));
277 var cif
= new
CCodeIfStatement (type_check
, type_block
);
278 if (clastif
== null) {
279 fragment
.append (cif
);
281 clastif
.false_statement
= cif
;
287 return new
CCodeIdentifier (temp_name
);
290 CCodeExpression
read_hash_table (CCodeFragment fragment
, ObjectType type
, CCodeExpression iter_expr
) {
291 string temp_name
= "_tmp%d_".printf (next_temp_var_id
++);
292 string subiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
293 string entryiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
295 var type_args
= type
.get_type_arguments ();
296 assert (type_args
.size
== 2);
297 var key_type
= type_args
.get (0);
298 var value_type
= type_args
.get (1);
300 var cdecl
= new
CCodeDeclaration ("GHashTable*");
301 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
));
302 fragment
.append (cdecl
);
304 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
305 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
306 fragment
.append (cdecl
);
308 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
309 cdecl
.add_declarator (new
CCodeVariableDeclarator (entryiter_name
));
310 fragment
.append (cdecl
);
312 var hash_table_new
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_hash_table_new_full"));
313 if (key_type
.data_type
== string_type
.data_type
) {
314 hash_table_new
.add_argument (new
CCodeIdentifier ("g_str_hash"));
315 hash_table_new
.add_argument (new
CCodeIdentifier ("g_str_equal"));
317 hash_table_new
.add_argument (new
CCodeIdentifier ("g_direct_hash"));
318 hash_table_new
.add_argument (new
CCodeIdentifier ("g_direct_equal"));
320 if (key_type
.data_type
== string_type
.data_type
) {
321 hash_table_new
.add_argument (new
CCodeIdentifier ("g_free"));
323 hash_table_new
.add_argument (new
CCodeIdentifier ("NULL"));
325 if (value_type
.data_type
== string_type
.data_type
) {
326 hash_table_new
.add_argument (new
CCodeIdentifier ("g_free"));
328 hash_table_new
.add_argument (new
CCodeIdentifier ("NULL"));
330 fragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier (temp_name
), hash_table_new
)));
332 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_recurse"));
333 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
334 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
335 fragment
.append (new
CCodeExpressionStatement (iter_call
));
337 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_get_arg_type"));
338 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
340 var cwhileblock
= new
CCodeBlock ();
341 var cwhilefragment
= new
CCodeFragment ();
342 cwhileblock
.add_statement (cwhilefragment
);
343 var cwhile
= new
CCodeWhileStatement (iter_call
, cwhileblock
);
345 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_recurse"));
346 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
347 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (entryiter_name
)));
348 cwhilefragment
.append (new
CCodeExpressionStatement (iter_call
));
350 cdecl
= new
CCodeDeclaration (key_type
.get_cname ());
351 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_key"));
352 cwhilefragment
.append (cdecl
);
354 cdecl
= new
CCodeDeclaration (value_type
.get_cname ());
355 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_value"));
356 cwhilefragment
.append (cdecl
);
358 var key_expr
= read_expression (cwhilefragment
, key_type
, new
CCodeIdentifier (entryiter_name
), null);
359 cwhilefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_key"), key_expr
)));
361 var value_expr
= read_expression (cwhilefragment
, value_type
, new
CCodeIdentifier (entryiter_name
), null);
362 cwhilefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_value"), value_expr
)));
364 var hash_table_insert
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_hash_table_insert"));
365 hash_table_insert
.add_argument (new
CCodeIdentifier (temp_name
));
366 hash_table_insert
.add_argument (convert_to_generic_pointer (new
CCodeIdentifier ("_key"), key_type
));
367 hash_table_insert
.add_argument (convert_to_generic_pointer (new
CCodeIdentifier ("_value"), value_type
));
368 cwhilefragment
.append (new
CCodeExpressionStatement (hash_table_insert
));
370 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_next"));
371 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
372 cwhilefragment
.append (new
CCodeExpressionStatement (iter_call
));
374 fragment
.append (cwhile
);
376 return new
CCodeIdentifier (temp_name
);
379 public CCodeExpression?
read_expression (CCodeFragment fragment
, DataType type
, CCodeExpression iter_expr
, CCodeExpression? expr
) {
380 BasicTypeInfo basic_type
;
381 CCodeExpression result
= null;
382 if (get_basic_type_info (get_type_signature (type
), out basic_type
)) {
383 result
= read_basic (fragment
, basic_type
, iter_expr
);
384 } else if (type is ArrayType
) {
385 result
= read_array (fragment
, (ArrayType
) type
, iter_expr
, expr
);
386 } else if (type
.data_type is Struct
) {
387 var st
= (Struct
) type
.data_type
;
388 if (type
.data_type
.get_full_name () == "GLib.Value") {
389 result
= read_value (fragment
, iter_expr
);
391 result
= read_struct (fragment
, st
, iter_expr
);
394 var csizeof
= new
CCodeFunctionCall (new
CCodeIdentifier ("sizeof"));
395 csizeof
.add_argument (new
CCodeIdentifier (st
.get_cname ()));
396 var cdup
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_memdup"));
397 cdup
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, result
));
398 cdup
.add_argument (csizeof
);
401 } else if (type is ObjectType
) {
402 if (type
.data_type
.get_full_name () == "GLib.HashTable") {
403 result
= read_hash_table (fragment
, (ObjectType
) type
, iter_expr
);
406 Report
.error (type
.source_reference
, "D-Bus deserialization of type `%s' is not supported".printf (type
.to_string ()));
410 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_next"));
411 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
412 fragment
.append (new
CCodeExpressionStatement (iter_call
));
417 void write_basic (CCodeFragment fragment
, BasicTypeInfo basic_type
, CCodeExpression iter_expr
, CCodeExpression expr
) {
418 string temp_name
= "_tmp%d_".printf (next_temp_var_id
++);
420 var cdecl
= new
CCodeDeclaration (basic_type
.cname
);
421 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
));
422 fragment
.append (cdecl
);
424 fragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier (temp_name
), expr
)));
426 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_append_basic"));
427 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
428 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_" + basic_type
.type_name
));
429 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (temp_name
)));
430 fragment
.append (new
CCodeExpressionStatement (iter_call
));
433 void write_array (CCodeFragment fragment
, ArrayType array_type
, CCodeExpression iter_expr
, CCodeExpression array_expr
) {
434 string array_iter_name
= "_tmp%d_".printf (next_temp_var_id
++);
436 var cdecl
= new
CCodeDeclaration (array_type
.get_cname ());
437 cdecl
.add_declarator (new
CCodeVariableDeclarator (array_iter_name
));
438 fragment
.append (cdecl
);
440 fragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier (array_iter_name
), array_expr
)));
442 write_array_dim (fragment
, array_type
, 1, iter_expr
, array_expr
, new
CCodeIdentifier (array_iter_name
));
445 void write_array_dim (CCodeFragment fragment
, ArrayType array_type
, int dim
, CCodeExpression iter_expr
, CCodeExpression array_expr
, CCodeExpression array_iter_expr
) {
446 string subiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
447 string index_name
= "_tmp%d_".printf (next_temp_var_id
++);
449 var cdecl
= new
CCodeDeclaration ("DBusMessageIter");
450 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
451 fragment
.append (cdecl
);
453 cdecl
= new
CCodeDeclaration ("int");
454 cdecl
.add_declarator (new
CCodeVariableDeclarator (index_name
));
455 fragment
.append (cdecl
);
457 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
458 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
459 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_ARRAY"));
460 iter_call
.add_argument (new
CCodeConstant ("\"%s%s\"".printf (string.nfill (array_type
.rank
- dim
, 'a'), get_type_signature (array_type
.element_type
))));
461 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
462 fragment
.append (new
CCodeExpressionStatement (iter_call
));
464 var cforblock
= new
CCodeBlock ();
465 var cforfragment
= new
CCodeFragment ();
466 cforblock
.add_statement (cforfragment
);
467 var cfor
= new
CCodeForStatement (new
CCodeBinaryExpression (CCodeBinaryOperator
.LESS_THAN
, new
CCodeIdentifier (index_name
), get_array_length (array_expr
, dim
)), cforblock
);
468 cfor
.add_initializer (new
CCodeAssignment (new
CCodeIdentifier (index_name
), new
CCodeConstant ("0")));
469 cfor
.add_iterator (new
CCodeUnaryExpression (CCodeUnaryOperator
.POSTFIX_INCREMENT
, new
CCodeIdentifier (index_name
)));
471 if (dim
< array_type
.rank
) {
472 write_array_dim (cforfragment
, array_type
, dim
+ 1, new
CCodeIdentifier (subiter_name
), array_expr
, array_iter_expr
);
474 var element_expr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, array_iter_expr
);
475 write_expression (cforfragment
, array_type
.element_type
, new
CCodeIdentifier (subiter_name
), element_expr
);
477 var array_iter_incr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POSTFIX_INCREMENT
, array_iter_expr
);
478 cforfragment
.append (new
CCodeExpressionStatement (array_iter_incr
));
480 fragment
.append (cfor
);
482 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
483 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
484 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
485 fragment
.append (new
CCodeExpressionStatement (iter_call
));
488 void write_struct (CCodeFragment fragment
, Struct st
, CCodeExpression iter_expr
, CCodeExpression struct_expr
) {
489 string subiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
491 var cdecl
= new
CCodeDeclaration ("DBusMessageIter");
492 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
493 fragment
.append (cdecl
);
495 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
496 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
497 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_STRUCT"));
498 iter_call
.add_argument (new
CCodeConstant ("NULL"));
499 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
500 fragment
.append (new
CCodeExpressionStatement (iter_call
));
502 foreach (Field f
in st
.get_fields ()) {
503 if (f
.binding
!= MemberBinding
.INSTANCE
) {
507 write_expression (fragment
, f
.field_type
, new
CCodeIdentifier (subiter_name
), new
CCodeMemberAccess (struct_expr
, f
.get_cname ()));
510 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
511 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
512 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
513 fragment
.append (new
CCodeExpressionStatement (iter_call
));
516 void write_value (CCodeFragment fragment
, CCodeExpression iter_expr
, CCodeExpression expr
) {
517 string subiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
519 var cdecl
= new
CCodeDeclaration ("DBusMessageIter");
520 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
521 fragment
.append (cdecl
);
523 CCodeIfStatement clastif
= null;
525 foreach (BasicTypeInfo basic_type
in basic_types
) {
526 // ensure that there is only one case per GType
527 if (basic_type
.get_value_function
== null) {
531 var type_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE"));
532 type_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, expr
));
533 var type_check
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, type_call
, new
CCodeIdentifier (basic_type
.gtype
));
535 var type_block
= new
CCodeBlock ();
536 var type_fragment
= new
CCodeFragment ();
537 type_block
.add_statement (type_fragment
);
539 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
540 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
541 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_VARIANT"));
542 iter_call
.add_argument (new
CCodeConstant ("\"%s\"".printf (basic_type
.signature
)));
543 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
544 type_fragment
.append (new
CCodeExpressionStatement (iter_call
));
546 var value_get
= new
CCodeFunctionCall (new
CCodeIdentifier (basic_type
.get_value_function
));
547 value_get
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, expr
));
549 write_basic (type_fragment
, basic_type
, new
CCodeIdentifier (subiter_name
), value_get
);
551 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
552 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
553 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
554 type_fragment
.append (new
CCodeExpressionStatement (iter_call
));
556 var cif
= new
CCodeIfStatement (type_check
, type_block
);
557 if (clastif
== null) {
558 fragment
.append (cif
);
560 clastif
.false_statement
= cif
;
567 void write_hash_table (CCodeFragment fragment
, ObjectType type
, CCodeExpression iter_expr
, CCodeExpression hash_table_expr
) {
568 string subiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
569 string entryiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
570 string tableiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
571 string key_name
= "_tmp%d_".printf (next_temp_var_id
++);
572 string value_name
= "_tmp%d_".printf (next_temp_var_id
++);
574 var type_args
= type
.get_type_arguments ();
575 assert (type_args
.size
== 2);
576 var key_type
= type_args
.get (0);
577 var value_type
= type_args
.get (1);
579 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
580 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
581 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_ARRAY"));
582 iter_call
.add_argument (new
CCodeConstant ("\"{%s%s}\"".printf (get_type_signature (key_type
), get_type_signature (value_type
))));
583 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
584 fragment
.append (new
CCodeExpressionStatement (iter_call
));
586 var cdecl
= new
CCodeDeclaration ("DBusMessageIter");
587 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
588 cdecl
.add_declarator (new
CCodeVariableDeclarator (entryiter_name
));
589 fragment
.append (cdecl
);
591 cdecl
= new
CCodeDeclaration ("GHashTableIter");
592 cdecl
.add_declarator (new
CCodeVariableDeclarator (tableiter_name
));
593 fragment
.append (cdecl
);
595 cdecl
= new
CCodeDeclaration ("gpointer");
596 cdecl
.add_declarator (new
CCodeVariableDeclarator (key_name
));
597 cdecl
.add_declarator (new
CCodeVariableDeclarator (value_name
));
598 fragment
.append (cdecl
);
600 var iter_init_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_hash_table_iter_init"));
601 iter_init_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (tableiter_name
)));
602 iter_init_call
.add_argument (hash_table_expr
);
603 fragment
.append (new
CCodeExpressionStatement (iter_init_call
));
605 var iter_next_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_hash_table_iter_next"));
606 iter_next_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (tableiter_name
)));
607 iter_next_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (key_name
)));
608 iter_next_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (value_name
)));
610 var cwhileblock
= new
CCodeBlock ();
611 var cwhilefragment
= new
CCodeFragment ();
612 cwhileblock
.add_statement (cwhilefragment
);
613 var cwhile
= new
CCodeWhileStatement (iter_next_call
, cwhileblock
);
615 cdecl
= new
CCodeDeclaration (key_type
.get_cname ());
616 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_key"));
617 cwhilefragment
.append (cdecl
);
619 cdecl
= new
CCodeDeclaration (value_type
.get_cname ());
620 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_value"));
621 cwhilefragment
.append (cdecl
);
623 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
624 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
625 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_DICT_ENTRY"));
626 iter_call
.add_argument (new
CCodeConstant ("NULL"));
627 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (entryiter_name
)));
628 cwhilefragment
.append (new
CCodeExpressionStatement (iter_call
));
630 cwhilefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_key"), convert_from_generic_pointer (new
CCodeIdentifier (key_name
), key_type
))));
631 cwhilefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_value"), convert_from_generic_pointer (new
CCodeIdentifier (value_name
), value_type
))));
633 write_expression (cwhilefragment
, key_type
, new
CCodeIdentifier (entryiter_name
), new
CCodeIdentifier ("_key"));
634 write_expression (cwhilefragment
, value_type
, new
CCodeIdentifier (entryiter_name
), new
CCodeIdentifier ("_value"));
636 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
637 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
638 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (entryiter_name
)));
639 cwhilefragment
.append (new
CCodeExpressionStatement (iter_call
));
641 fragment
.append (cwhile
);
643 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
644 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
645 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
646 fragment
.append (new
CCodeExpressionStatement (iter_call
));
649 public void write_expression (CCodeFragment fragment
, DataType type
, CCodeExpression iter_expr
, CCodeExpression expr
) {
650 BasicTypeInfo basic_type
;
651 if (get_basic_type_info (get_type_signature (type
), out basic_type
)) {
652 write_basic (fragment
, basic_type
, iter_expr
, expr
);
653 } else if (type is ArrayType
) {
654 write_array (fragment
, (ArrayType
) type
, iter_expr
, expr
);
655 } else if (type
.data_type is Struct
) {
658 st_expr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, st_expr
);
660 if (type
.data_type
.get_full_name () == "GLib.Value") {
661 write_value (fragment
, iter_expr
, st_expr
);
663 write_struct (fragment
, (Struct
) type
.data_type
, iter_expr
, st_expr
);
665 } else if (type is ObjectType
) {
666 if (type
.data_type
.get_full_name () == "GLib.HashTable") {
667 write_hash_table (fragment
, (ObjectType
) type
, iter_expr
, expr
);
670 Report
.error (type
.source_reference
, "D-Bus serialization of type `%s' is not supported".printf (type
.to_string ()));