3 * Copyright (C) 2008-2010 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 public 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 static bool is_string_marshalled_enum (TypeSymbol? symbol
) {
49 if (symbol
!= null && symbol is Enum
) {
50 var dbus
= symbol
.get_attribute ("DBus");
51 return dbus
!= null && dbus
.get_bool ("use_string_marshalling");
56 string get_dbus_value (EnumValue value
, string default_value
) {
57 var dbus
= value
.get_attribute ("DBus");
62 string dbus_value
= dbus
.get_string ("value");
63 if (dbus_value
== null) {
69 public static string?
get_dbus_name (TypeSymbol symbol
) {
70 var dbus
= symbol
.get_attribute ("DBus");
75 return dbus
.get_string ("name");
78 public static string get_dbus_name_for_member (Symbol symbol
) {
79 var dbus
= symbol
.get_attribute ("DBus");
80 if (dbus
!= null && dbus
.has_argument ("name")) {
81 return dbus
.get_string ("name");
84 return Symbol
.lower_case_to_camel_case (symbol
.name
);
87 bool get_basic_type_info (string signature
, out BasicTypeInfo basic_type
) {
88 foreach (BasicTypeInfo info
in basic_types
) {
89 if (info
.signature
== signature
) {
97 public static string?
get_type_signature (DataType datatype
) {
98 var array_type
= datatype as ArrayType
;
100 if (array_type
!= null) {
101 string element_type_signature
= get_type_signature (array_type
.element_type
);
103 if (element_type_signature
== null) {
107 return string.nfill (array_type
.rank
, 'a') + element_type_signature
;
108 } else if (is_string_marshalled_enum (datatype
.data_type
)) {
110 } else if (datatype
.data_type
!= null) {
113 var ccode
= datatype
.data_type
.get_attribute ("CCode");
115 sig
= ccode
.get_string ("type_signature");
118 var st
= datatype
.data_type as Struct
;
119 var en
= datatype
.data_type as Enum
;
120 if (sig
== null && st
!= null) {
121 var str
= new
StringBuilder ();
123 foreach (Field f
in st
.get_fields ()) {
124 if (f
.binding
== MemberBinding
.INSTANCE
) {
125 str
.append (get_type_signature (f
.variable_type
));
130 } else if (sig
== null && en
!= null) {
138 var type_args
= datatype
.get_type_arguments ();
139 if (sig
!= null && sig
.str ("%s") != null && type_args
.size
> 0) {
140 string element_sig
= "";
141 foreach (DataType type_arg
in type_args
) {
142 var s
= get_type_signature (type_arg
);
148 sig
= sig
.printf (element_sig
);
157 public override void visit_enum (Enum en
) {
158 base.visit_enum (en
);
160 if (is_string_marshalled_enum (en
)) {
162 cfile
.add_include ("string.h");
163 cfile
.add_include ("dbus/dbus-glib.h");
165 cfile
.add_function (generate_enum_from_string_function (en
));
166 cfile
.add_function (generate_enum_to_string_function (en
));
170 public override bool generate_enum_declaration (Enum en
, CCodeFile decl_space
) {
171 if (base.generate_enum_declaration (en
, decl_space
)) {
172 if (is_string_marshalled_enum (en
)) {
173 decl_space
.add_function_declaration (generate_enum_from_string_function_declaration (en
));
174 decl_space
.add_function_declaration (generate_enum_to_string_function_declaration (en
));
181 CCodeExpression?
get_array_length (CCodeExpression expr
, int dim
) {
182 var id
= expr as CCodeIdentifier
;
183 var ma
= expr as CCodeMemberAccess
;
185 return new
CCodeIdentifier ("%s_length%d".printf (id
.name
, dim
));
186 } else if (ma
!= null) {
188 return new CCodeMemberAccess
.pointer (ma
.inner
, "%s_length%d".printf (ma
.member_name
, dim
));
190 return new
CCodeMemberAccess (ma
.inner
, "%s_length%d".printf (ma
.member_name
, dim
));
193 // must be NULL-terminated
194 var len_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strv_length"));
195 len_call
.add_argument (expr
);
200 CCodeExpression?
generate_enum_value_from_string (CCodeFragment fragment
, EnumValueType type
, CCodeExpression? expr
) {
201 var en
= type
.type_symbol as Enum
;
202 var from_string_name
= "%s_from_string".printf (en
.get_lower_case_cname (null));
204 var from_string_call
= new
CCodeFunctionCall (new
CCodeIdentifier (from_string_name
));
205 from_string_call
.add_argument (expr
);
206 from_string_call
.add_argument (new
CCodeConstant ("NULL"));
208 return from_string_call
;
211 public CCodeFunction
generate_enum_from_string_function_declaration (Enum en
) {
212 var from_string_name
= "%s_from_string".printf (en
.get_lower_case_cname (null));
214 var from_string_func
= new
CCodeFunction (from_string_name
, en
.get_cname ());
215 from_string_func
.add_parameter (new
CCodeParameter ("str", "const char*"));
216 from_string_func
.add_parameter (new
CCodeParameter ("error", "GError**"));
218 return from_string_func
;
221 public CCodeFunction
generate_enum_from_string_function (Enum en
) {
222 var from_string_name
= "%s_from_string".printf (en
.get_lower_case_cname (null));
224 var from_string_func
= new
CCodeFunction (from_string_name
, en
.get_cname ());
225 from_string_func
.add_parameter (new
CCodeParameter ("str", "const char*"));
226 from_string_func
.add_parameter (new
CCodeParameter ("error", "GError**"));
228 var from_string_block
= new
CCodeBlock ();
229 from_string_func
.block
= from_string_block
;
231 var cdecl
= new
CCodeDeclaration (en
.get_cname ());
232 cdecl
.add_declarator (new
CCodeVariableDeclarator ("value"));
233 from_string_block
.add_statement (cdecl
);
235 CCodeStatement if_else_if
= null;
236 CCodeIfStatement last_statement
= null;
237 foreach (EnumValue enum_value
in en
.get_values ()) {
238 var true_block
= new
CCodeBlock ();
239 true_block
.suppress_newline
= true;
240 true_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("value"), new
CCodeIdentifier (enum_value
.get_cname ()))));
242 string dbus_value
= get_dbus_value (enum_value
, enum_value
.name
);
243 var string_comparison
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
244 string_comparison
.add_argument (new
CCodeIdentifier ("str"));
245 string_comparison
.add_argument (new
CCodeConstant ("\"%s\"".printf (dbus_value
)));
246 var stmt
= new
CCodeIfStatement (new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, string_comparison
, new
CCodeConstant ("0")), true_block
);
248 if (last_statement
!= null) {
249 last_statement
.false_statement
= stmt
;
253 last_statement
= stmt
;
256 var error_block
= new
CCodeBlock ();
257 error_block
.suppress_newline
= true;
259 var set_error_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_set_error"));
260 set_error_call
.add_argument (new
CCodeIdentifier ("error"));
261 set_error_call
.add_argument (new
CCodeIdentifier ("DBUS_GERROR"));
262 set_error_call
.add_argument (new
CCodeIdentifier ("DBUS_GERROR_INVALID_ARGS"));
263 set_error_call
.add_argument (new
CCodeConstant ("\"%s\""));
264 set_error_call
.add_argument (new
CCodeConstant ("\"Invalid enumeration value\""));
265 error_block
.add_statement (new
CCodeExpressionStatement (set_error_call
));
267 last_statement
.false_statement
= error_block
;
268 from_string_block
.add_statement (if_else_if
);
270 from_string_block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("value")));
272 return from_string_func
;
275 CCodeExpression
read_basic (CCodeFragment fragment
, BasicTypeInfo basic_type
, CCodeExpression iter_expr
, bool transfer
= false) {
276 string temp_name
= "_tmp%d_".printf (next_temp_var_id
++);
278 var cdecl
= new
CCodeDeclaration (basic_type
.cname
);
279 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
));
280 fragment
.append (cdecl
);
282 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_get_basic"));
283 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
284 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (temp_name
)));
285 fragment
.append (new
CCodeExpressionStatement (iter_call
));
287 var temp_result
= new
CCodeIdentifier (temp_name
);
290 && (basic_type
.signature
== "s"
291 || basic_type
.signature
== "o"
292 || basic_type
.signature
== "g")) {
293 var dup_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strdup"));
294 dup_call
.add_argument (temp_result
);
301 CCodeExpression
read_array (CCodeFragment fragment
, ArrayType array_type
, CCodeExpression iter_expr
, CCodeExpression? expr
) {
302 string temp_name
= "_tmp%d_".printf (next_temp_var_id
++);
304 var new_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_new"));
305 new_call
.add_argument (new
CCodeIdentifier (array_type
.element_type
.get_cname ()));
306 // add one extra element for NULL-termination
307 new_call
.add_argument (new
CCodeConstant ("5"));
309 var cdecl
= new
CCodeDeclaration (array_type
.get_cname ());
310 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
, new_call
));
311 fragment
.append (cdecl
);
313 cdecl
= new
CCodeDeclaration ("int");
314 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
+ "_length", new
CCodeConstant ("0")));
315 fragment
.append (cdecl
);
317 cdecl
= new
CCodeDeclaration ("int");
318 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
+ "_size", new
CCodeConstant ("4")));
319 fragment
.append (cdecl
);
321 read_array_dim (fragment
, array_type
, 1, temp_name
, iter_expr
, expr
);
323 if (array_type
.element_type
.is_reference_type_or_type_parameter ()) {
324 // NULL terminate array
325 var length
= new
CCodeIdentifier (temp_name
+ "_length");
326 var element_access
= new
CCodeElementAccess (new
CCodeIdentifier (temp_name
), length
);
327 fragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (element_access
, new
CCodeIdentifier ("NULL"))));
330 return new
CCodeIdentifier (temp_name
);
333 void read_array_dim (CCodeFragment fragment
, ArrayType array_type
, int dim
, string temp_name
, CCodeExpression iter_expr
, CCodeExpression? expr
) {
334 string subiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
336 var cdecl
= new
CCodeDeclaration ("int");
337 cdecl
.add_declarator (new
CCodeVariableDeclarator ("%s_length%d".printf (temp_name
, dim
), new
CCodeConstant ("0")));
338 fragment
.append (cdecl
);
340 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
341 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
342 fragment
.append (cdecl
);
344 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_recurse"));
345 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
346 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
347 fragment
.append (new
CCodeExpressionStatement (iter_call
));
349 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_get_arg_type"));
350 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
352 var cforblock
= new
CCodeBlock ();
353 var cforfragment
= new
CCodeFragment ();
354 cforblock
.add_statement (cforfragment
);
355 var cfor
= new
CCodeForStatement (iter_call
, cforblock
);
356 cfor
.add_iterator (new
CCodeUnaryExpression (CCodeUnaryOperator
.POSTFIX_INCREMENT
, new
CCodeIdentifier ("%s_length%d".printf (temp_name
, dim
))));
358 if (dim
< array_type
.rank
) {
359 read_array_dim (cforfragment
, array_type
, dim
+ 1, temp_name
, new
CCodeIdentifier (subiter_name
), expr
);
361 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_next"));
362 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
363 cforfragment
.append (new
CCodeExpressionStatement (iter_call
));
365 var size_check
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, new
CCodeIdentifier (temp_name
+ "_size"), new
CCodeIdentifier (temp_name
+ "_length"));
366 var renew_block
= new
CCodeBlock ();
368 // tmp_size = (2 * tmp_size);
369 var new_size
= new
CCodeBinaryExpression (CCodeBinaryOperator
.MUL
, new
CCodeConstant ("2"), new
CCodeIdentifier (temp_name
+ "_size"));
370 renew_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier (temp_name
+ "_size"), new_size
)));
372 var renew_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_renew"));
373 renew_call
.add_argument (new
CCodeIdentifier (array_type
.element_type
.get_cname ()));
374 renew_call
.add_argument (new
CCodeIdentifier (temp_name
));
375 // add one extra element for NULL-termination
376 renew_call
.add_argument (new
CCodeBinaryExpression (CCodeBinaryOperator
.PLUS
, new
CCodeIdentifier (temp_name
+ "_size"), new
CCodeConstant ("1")));
377 var renew_stmt
= new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier (temp_name
), renew_call
));
378 renew_block
.add_statement (renew_stmt
);
380 var cif
= new
CCodeIfStatement (size_check
, renew_block
);
381 cforfragment
.append (cif
);
383 var element_access
= new
CCodeElementAccess (new
CCodeIdentifier (temp_name
), new
CCodeUnaryExpression (CCodeUnaryOperator
.POSTFIX_INCREMENT
, new
CCodeIdentifier (temp_name
+ "_length")));
384 var element_expr
= read_expression (cforfragment
, array_type
.element_type
, new
CCodeIdentifier (subiter_name
), null);
385 cforfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (element_access
, element_expr
)));
388 fragment
.append (cfor
);
391 fragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (get_array_length (expr
, dim
), new
CCodeIdentifier ("%s_length%d".printf (temp_name
, dim
)))));
395 CCodeExpression
read_struct (CCodeFragment fragment
, Struct st
, CCodeExpression iter_expr
) {
396 string temp_name
= "_tmp%d_".printf (next_temp_var_id
++);
397 string subiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
399 var cdecl
= new
CCodeDeclaration (st
.get_cname ());
400 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
));
401 fragment
.append (cdecl
);
403 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
404 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
405 fragment
.append (cdecl
);
407 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_recurse"));
408 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
409 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
410 fragment
.append (new
CCodeExpressionStatement (iter_call
));
412 foreach (Field f
in st
.get_fields ()) {
413 if (f
.binding
!= MemberBinding
.INSTANCE
) {
417 var field_expr
= read_expression (fragment
, f
.variable_type
, new
CCodeIdentifier (subiter_name
), new
CCodeMemberAccess (new
CCodeIdentifier (temp_name
), f
.get_cname ()));
418 fragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeMemberAccess (new
CCodeIdentifier (temp_name
), f
.get_cname ()), field_expr
)));
421 return new
CCodeIdentifier (temp_name
);
424 CCodeExpression
read_value (CCodeFragment fragment
, CCodeExpression iter_expr
) {
425 string temp_name
= "_tmp%d_".printf (next_temp_var_id
++);
426 string subiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
428 // 0-initialize struct with struct initializer { 0 }
429 var cvalinit
= new
CCodeInitializerList ();
430 cvalinit
.append (new
CCodeConstant ("0"));
432 var cdecl
= new
CCodeDeclaration ("GValue");
433 cdecl
.add_declarator (new CCodeVariableDeclarator
.zero (temp_name
, cvalinit
));
434 fragment
.append (cdecl
);
436 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
437 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
438 fragment
.append (cdecl
);
440 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_recurse"));
441 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
442 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
443 fragment
.append (new
CCodeExpressionStatement (iter_call
));
445 CCodeIfStatement clastif
= null;
447 foreach (BasicTypeInfo basic_type
in basic_types
) {
448 var type_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_get_arg_type"));
449 type_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
450 var type_check
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, type_call
, new
CCodeIdentifier ("DBUS_TYPE_" + basic_type
.type_name
));
452 var type_block
= new
CCodeBlock ();
453 var type_fragment
= new
CCodeFragment ();
454 type_block
.add_statement (type_fragment
);
455 var result
= read_basic (type_fragment
, basic_type
, new
CCodeIdentifier (subiter_name
));
457 var value_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_init"));
458 value_init
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (temp_name
)));
459 value_init
.add_argument (new
CCodeIdentifier (basic_type
.gtype
));
460 type_fragment
.append (new
CCodeExpressionStatement (value_init
));
462 var value_set
= new
CCodeFunctionCall (new
CCodeIdentifier (basic_type
.set_value_function
));
463 value_set
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (temp_name
)));
464 value_set
.add_argument (result
);
465 type_fragment
.append (new
CCodeExpressionStatement (value_set
));
467 var cif
= new
CCodeIfStatement (type_check
, type_block
);
468 if (clastif
== null) {
469 fragment
.append (cif
);
471 clastif
.false_statement
= cif
;
477 // handle string arrays
478 var type_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_get_arg_type"));
479 type_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
480 var type_check
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, type_call
, new
CCodeIdentifier ("DBUS_TYPE_ARRAY"));
482 type_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_get_element_type"));
483 type_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
484 var element_type_check
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, type_call
, new
CCodeIdentifier ("DBUS_TYPE_STRING"));
486 type_check
= new
CCodeBinaryExpression (CCodeBinaryOperator
.AND
, type_check
, element_type_check
);
488 var type_block
= new
CCodeBlock ();
489 var type_fragment
= new
CCodeFragment ();
490 type_block
.add_statement (type_fragment
);
491 var result
= read_array (type_fragment
, new
ArrayType (string_type
, 1, null), new
CCodeIdentifier (subiter_name
), null);
493 var value_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_init"));
494 value_init
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (temp_name
)));
495 value_init
.add_argument (new
CCodeIdentifier ("G_TYPE_STRV"));
496 type_fragment
.append (new
CCodeExpressionStatement (value_init
));
498 var value_set
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_take_boxed"));
499 value_set
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (temp_name
)));
500 value_set
.add_argument (result
);
501 type_fragment
.append (new
CCodeExpressionStatement (value_set
));
503 var cif
= new
CCodeIfStatement (type_check
, type_block
);
504 if (clastif
== null) {
505 fragment
.append (cif
);
507 clastif
.false_statement
= cif
;
512 return new
CCodeIdentifier (temp_name
);
515 CCodeExpression
read_hash_table (CCodeFragment fragment
, ObjectType type
, CCodeExpression iter_expr
) {
516 string temp_name
= "_tmp%d_".printf (next_temp_var_id
++);
517 string subiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
518 string entryiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
520 var type_args
= type
.get_type_arguments ();
521 assert (type_args
.size
== 2);
522 var key_type
= type_args
.get (0);
523 var value_type
= type_args
.get (1);
525 var cdecl
= new
CCodeDeclaration ("GHashTable*");
526 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
));
527 fragment
.append (cdecl
);
529 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
530 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
531 fragment
.append (cdecl
);
533 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
534 cdecl
.add_declarator (new
CCodeVariableDeclarator (entryiter_name
));
535 fragment
.append (cdecl
);
537 var hash_table_new
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_hash_table_new_full"));
538 if (key_type
.data_type
== string_type
.data_type
) {
539 hash_table_new
.add_argument (new
CCodeIdentifier ("g_str_hash"));
540 hash_table_new
.add_argument (new
CCodeIdentifier ("g_str_equal"));
542 hash_table_new
.add_argument (new
CCodeIdentifier ("g_direct_hash"));
543 hash_table_new
.add_argument (new
CCodeIdentifier ("g_direct_equal"));
545 if (key_type
.data_type
== string_type
.data_type
) {
546 hash_table_new
.add_argument (new
CCodeIdentifier ("g_free"));
548 hash_table_new
.add_argument (new
CCodeIdentifier ("NULL"));
550 if (value_type
.data_type
== string_type
.data_type
) {
551 hash_table_new
.add_argument (new
CCodeIdentifier ("g_free"));
553 hash_table_new
.add_argument (new
CCodeIdentifier ("NULL"));
555 fragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier (temp_name
), hash_table_new
)));
557 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_recurse"));
558 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
559 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
560 fragment
.append (new
CCodeExpressionStatement (iter_call
));
562 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_get_arg_type"));
563 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
565 var cwhileblock
= new
CCodeBlock ();
566 var cwhilefragment
= new
CCodeFragment ();
567 cwhileblock
.add_statement (cwhilefragment
);
568 var cwhile
= new
CCodeWhileStatement (iter_call
, cwhileblock
);
570 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_recurse"));
571 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
572 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (entryiter_name
)));
573 cwhilefragment
.append (new
CCodeExpressionStatement (iter_call
));
575 cdecl
= new
CCodeDeclaration (key_type
.get_cname ());
576 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_key"));
577 cwhilefragment
.append (cdecl
);
579 cdecl
= new
CCodeDeclaration (value_type
.get_cname ());
580 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_value"));
581 cwhilefragment
.append (cdecl
);
583 var key_expr
= read_expression (cwhilefragment
, key_type
, new
CCodeIdentifier (entryiter_name
), null);
584 cwhilefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_key"), key_expr
)));
586 var value_expr
= read_expression (cwhilefragment
, value_type
, new
CCodeIdentifier (entryiter_name
), null);
587 cwhilefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_value"), value_expr
)));
589 var hash_table_insert
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_hash_table_insert"));
590 hash_table_insert
.add_argument (new
CCodeIdentifier (temp_name
));
591 hash_table_insert
.add_argument (convert_to_generic_pointer (new
CCodeIdentifier ("_key"), key_type
));
592 hash_table_insert
.add_argument (convert_to_generic_pointer (new
CCodeIdentifier ("_value"), value_type
));
593 cwhilefragment
.append (new
CCodeExpressionStatement (hash_table_insert
));
595 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_next"));
596 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
597 cwhilefragment
.append (new
CCodeExpressionStatement (iter_call
));
599 fragment
.append (cwhile
);
601 return new
CCodeIdentifier (temp_name
);
604 public CCodeExpression?
read_expression (CCodeFragment fragment
, DataType type
, CCodeExpression iter_expr
, CCodeExpression? expr
) {
605 BasicTypeInfo basic_type
;
606 CCodeExpression result
= null;
607 if (is_string_marshalled_enum (type
.data_type
)) {
608 get_basic_type_info ("s", out basic_type
);
609 result
= read_basic (fragment
, basic_type
, iter_expr
, true);
610 result
= generate_enum_value_from_string (fragment
, type as EnumValueType
, result
);
611 } else if (get_basic_type_info (get_type_signature (type
), out basic_type
)) {
612 result
= read_basic (fragment
, basic_type
, iter_expr
);
613 } else if (type is ArrayType
) {
614 result
= read_array (fragment
, (ArrayType
) type
, iter_expr
, expr
);
615 } else if (type
.data_type is Struct
) {
616 var st
= (Struct
) type
.data_type
;
617 if (type
.data_type
.get_full_name () == "GLib.Value") {
618 result
= read_value (fragment
, iter_expr
);
620 result
= read_struct (fragment
, st
, iter_expr
);
623 var csizeof
= new
CCodeFunctionCall (new
CCodeIdentifier ("sizeof"));
624 csizeof
.add_argument (new
CCodeIdentifier (st
.get_cname ()));
625 var cdup
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_memdup"));
626 cdup
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, result
));
627 cdup
.add_argument (csizeof
);
630 } else if (type is ObjectType
) {
631 if (type
.data_type
.get_full_name () == "GLib.HashTable") {
632 result
= read_hash_table (fragment
, (ObjectType
) type
, iter_expr
);
635 Report
.error (type
.source_reference
, "D-Bus deserialization of type `%s' is not supported".printf (type
.to_string ()));
639 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_next"));
640 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
641 fragment
.append (new
CCodeExpressionStatement (iter_call
));
646 CCodeExpression?
generate_enum_value_to_string (CCodeFragment fragment
, EnumValueType type
, CCodeExpression? expr
) {
647 var en
= type
.type_symbol as Enum
;
648 var to_string_name
= "%s_to_string".printf (en
.get_lower_case_cname (null));
650 var to_string_call
= new
CCodeFunctionCall (new
CCodeIdentifier (to_string_name
));
651 to_string_call
.add_argument (expr
);
653 return to_string_call
;
656 public CCodeFunction
generate_enum_to_string_function_declaration (Enum en
) {
657 var to_string_name
= "%s_to_string".printf (en
.get_lower_case_cname (null));
659 var to_string_func
= new
CCodeFunction (to_string_name
, "const char*");
660 to_string_func
.add_parameter (new
CCodeParameter ("value", en
.get_cname ()));
662 return to_string_func
;
665 public CCodeFunction
generate_enum_to_string_function (Enum en
) {
666 var to_string_name
= "%s_to_string".printf (en
.get_lower_case_cname (null));
668 var to_string_func
= new
CCodeFunction (to_string_name
, "const char*");
669 to_string_func
.add_parameter (new
CCodeParameter ("value", en
.get_cname ()));
671 var to_string_block
= new
CCodeBlock ();
672 to_string_func
.block
= to_string_block
;
674 var cdecl
= new
CCodeDeclaration ("const char *");
675 cdecl
.add_declarator (new
CCodeVariableDeclarator ("str"));
676 to_string_block
.add_statement (cdecl
);
678 var cswitch
= new
CCodeSwitchStatement (new
CCodeIdentifier ("value"));
679 foreach (EnumValue enum_value
in en
.get_values ()) {
680 string dbus_value
= get_dbus_value (enum_value
, enum_value
.name
);
681 cswitch
.add_statement (new
CCodeCaseStatement (new
CCodeIdentifier (enum_value
.get_cname ())));
682 cswitch
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("str"), new
CCodeConstant ("\"%s\"".printf (dbus_value
)))));
683 cswitch
.add_statement (new
CCodeBreakStatement ());
685 to_string_block
.add_statement (cswitch
);
687 to_string_block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("str")));
689 return to_string_func
;
692 void write_basic (CCodeFragment fragment
, BasicTypeInfo basic_type
, CCodeExpression iter_expr
, CCodeExpression expr
) {
693 string temp_name
= "_tmp%d_".printf (next_temp_var_id
++);
695 var cdecl
= new
CCodeDeclaration (basic_type
.cname
);
696 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
));
697 fragment
.append (cdecl
);
699 fragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier (temp_name
), expr
)));
701 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_append_basic"));
702 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
703 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_" + basic_type
.type_name
));
704 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (temp_name
)));
705 fragment
.append (new
CCodeExpressionStatement (iter_call
));
708 void write_array (CCodeFragment fragment
, ArrayType array_type
, CCodeExpression iter_expr
, CCodeExpression array_expr
) {
709 string array_iter_name
= "_tmp%d_".printf (next_temp_var_id
++);
711 var cdecl
= new
CCodeDeclaration (array_type
.get_cname ());
712 cdecl
.add_declarator (new
CCodeVariableDeclarator (array_iter_name
));
713 fragment
.append (cdecl
);
715 fragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier (array_iter_name
), array_expr
)));
717 write_array_dim (fragment
, array_type
, 1, iter_expr
, array_expr
, new
CCodeIdentifier (array_iter_name
));
720 void write_array_dim (CCodeFragment fragment
, ArrayType array_type
, int dim
, CCodeExpression iter_expr
, CCodeExpression array_expr
, CCodeExpression array_iter_expr
) {
721 string subiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
722 string index_name
= "_tmp%d_".printf (next_temp_var_id
++);
724 var cdecl
= new
CCodeDeclaration ("DBusMessageIter");
725 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
726 fragment
.append (cdecl
);
728 cdecl
= new
CCodeDeclaration ("int");
729 cdecl
.add_declarator (new
CCodeVariableDeclarator (index_name
));
730 fragment
.append (cdecl
);
732 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
733 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
734 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_ARRAY"));
735 iter_call
.add_argument (new
CCodeConstant ("\"%s%s\"".printf (string.nfill (array_type
.rank
- dim
, 'a'), get_type_signature (array_type
.element_type
))));
736 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
737 fragment
.append (new
CCodeExpressionStatement (iter_call
));
739 var cforblock
= new
CCodeBlock ();
740 var cforfragment
= new
CCodeFragment ();
741 cforblock
.add_statement (cforfragment
);
742 var cfor
= new
CCodeForStatement (new
CCodeBinaryExpression (CCodeBinaryOperator
.LESS_THAN
, new
CCodeIdentifier (index_name
), get_array_length (array_expr
, dim
)), cforblock
);
743 cfor
.add_initializer (new
CCodeAssignment (new
CCodeIdentifier (index_name
), new
CCodeConstant ("0")));
744 cfor
.add_iterator (new
CCodeUnaryExpression (CCodeUnaryOperator
.POSTFIX_INCREMENT
, new
CCodeIdentifier (index_name
)));
746 if (dim
< array_type
.rank
) {
747 write_array_dim (cforfragment
, array_type
, dim
+ 1, new
CCodeIdentifier (subiter_name
), array_expr
, array_iter_expr
);
749 var element_expr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, array_iter_expr
);
750 write_expression (cforfragment
, array_type
.element_type
, new
CCodeIdentifier (subiter_name
), element_expr
);
752 var array_iter_incr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POSTFIX_INCREMENT
, array_iter_expr
);
753 cforfragment
.append (new
CCodeExpressionStatement (array_iter_incr
));
755 fragment
.append (cfor
);
757 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
758 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
759 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
760 fragment
.append (new
CCodeExpressionStatement (iter_call
));
763 void write_struct (CCodeFragment fragment
, Struct st
, CCodeExpression iter_expr
, CCodeExpression struct_expr
) {
764 string subiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
766 var cdecl
= new
CCodeDeclaration ("DBusMessageIter");
767 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
768 fragment
.append (cdecl
);
770 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
771 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
772 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_STRUCT"));
773 iter_call
.add_argument (new
CCodeConstant ("NULL"));
774 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
775 fragment
.append (new
CCodeExpressionStatement (iter_call
));
777 foreach (Field f
in st
.get_fields ()) {
778 if (f
.binding
!= MemberBinding
.INSTANCE
) {
782 write_expression (fragment
, f
.variable_type
, new
CCodeIdentifier (subiter_name
), new
CCodeMemberAccess (struct_expr
, f
.get_cname ()));
785 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
786 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
787 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
788 fragment
.append (new
CCodeExpressionStatement (iter_call
));
791 void write_value (CCodeFragment fragment
, CCodeExpression iter_expr
, CCodeExpression expr
) {
792 string subiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
794 var cdecl
= new
CCodeDeclaration ("DBusMessageIter");
795 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
796 fragment
.append (cdecl
);
798 CCodeIfStatement clastif
= null;
800 foreach (BasicTypeInfo basic_type
in basic_types
) {
801 // ensure that there is only one case per GType
802 if (basic_type
.get_value_function
== null) {
806 var type_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE"));
807 type_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, expr
));
808 var type_check
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, type_call
, new
CCodeIdentifier (basic_type
.gtype
));
810 var type_block
= new
CCodeBlock ();
811 var type_fragment
= new
CCodeFragment ();
812 type_block
.add_statement (type_fragment
);
814 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
815 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
816 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_VARIANT"));
817 iter_call
.add_argument (new
CCodeConstant ("\"%s\"".printf (basic_type
.signature
)));
818 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
819 type_fragment
.append (new
CCodeExpressionStatement (iter_call
));
821 var value_get
= new
CCodeFunctionCall (new
CCodeIdentifier (basic_type
.get_value_function
));
822 value_get
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, expr
));
824 write_basic (type_fragment
, basic_type
, new
CCodeIdentifier (subiter_name
), value_get
);
826 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
827 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
828 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
829 type_fragment
.append (new
CCodeExpressionStatement (iter_call
));
831 var cif
= new
CCodeIfStatement (type_check
, type_block
);
832 if (clastif
== null) {
833 fragment
.append (cif
);
835 clastif
.false_statement
= cif
;
841 // handle string arrays
842 var type_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE"));
843 type_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, expr
));
844 var type_check
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, type_call
, new
CCodeIdentifier ("G_TYPE_STRV"));
846 var type_block
= new
CCodeBlock ();
847 var type_fragment
= new
CCodeFragment ();
848 type_block
.add_statement (type_fragment
);
850 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
851 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
852 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_VARIANT"));
853 iter_call
.add_argument (new
CCodeConstant ("\"as\""));
854 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
855 type_fragment
.append (new
CCodeExpressionStatement (iter_call
));
857 var value_get
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_get_boxed"));
858 value_get
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, expr
));
860 write_array (type_fragment
, new
ArrayType (string_type
, 1, null), new
CCodeIdentifier (subiter_name
), value_get
);
862 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
863 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
864 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
865 type_fragment
.append (new
CCodeExpressionStatement (iter_call
));
867 var cif
= new
CCodeIfStatement (type_check
, type_block
);
868 if (clastif
== null) {
869 fragment
.append (cif
);
871 clastif
.false_statement
= cif
;
877 void write_hash_table (CCodeFragment fragment
, ObjectType type
, CCodeExpression iter_expr
, CCodeExpression hash_table_expr
) {
878 string subiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
879 string entryiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
880 string tableiter_name
= "_tmp%d_".printf (next_temp_var_id
++);
881 string key_name
= "_tmp%d_".printf (next_temp_var_id
++);
882 string value_name
= "_tmp%d_".printf (next_temp_var_id
++);
884 var type_args
= type
.get_type_arguments ();
885 assert (type_args
.size
== 2);
886 var key_type
= type_args
.get (0);
887 var value_type
= type_args
.get (1);
889 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
890 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
891 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_ARRAY"));
892 iter_call
.add_argument (new
CCodeConstant ("\"{%s%s}\"".printf (get_type_signature (key_type
), get_type_signature (value_type
))));
893 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
894 fragment
.append (new
CCodeExpressionStatement (iter_call
));
896 var cdecl
= new
CCodeDeclaration ("DBusMessageIter");
897 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
898 cdecl
.add_declarator (new
CCodeVariableDeclarator (entryiter_name
));
899 fragment
.append (cdecl
);
901 cdecl
= new
CCodeDeclaration ("GHashTableIter");
902 cdecl
.add_declarator (new
CCodeVariableDeclarator (tableiter_name
));
903 fragment
.append (cdecl
);
905 cdecl
= new
CCodeDeclaration ("gpointer");
906 cdecl
.add_declarator (new
CCodeVariableDeclarator (key_name
));
907 cdecl
.add_declarator (new
CCodeVariableDeclarator (value_name
));
908 fragment
.append (cdecl
);
910 var iter_init_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_hash_table_iter_init"));
911 iter_init_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (tableiter_name
)));
912 iter_init_call
.add_argument (hash_table_expr
);
913 fragment
.append (new
CCodeExpressionStatement (iter_init_call
));
915 var iter_next_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_hash_table_iter_next"));
916 iter_next_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (tableiter_name
)));
917 iter_next_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (key_name
)));
918 iter_next_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (value_name
)));
920 var cwhileblock
= new
CCodeBlock ();
921 var cwhilefragment
= new
CCodeFragment ();
922 cwhileblock
.add_statement (cwhilefragment
);
923 var cwhile
= new
CCodeWhileStatement (iter_next_call
, cwhileblock
);
925 cdecl
= new
CCodeDeclaration (key_type
.get_cname ());
926 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_key"));
927 cwhilefragment
.append (cdecl
);
929 cdecl
= new
CCodeDeclaration (value_type
.get_cname ());
930 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_value"));
931 cwhilefragment
.append (cdecl
);
933 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
934 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
935 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_DICT_ENTRY"));
936 iter_call
.add_argument (new
CCodeConstant ("NULL"));
937 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (entryiter_name
)));
938 cwhilefragment
.append (new
CCodeExpressionStatement (iter_call
));
940 cwhilefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_key"), convert_from_generic_pointer (new
CCodeIdentifier (key_name
), key_type
))));
941 cwhilefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_value"), convert_from_generic_pointer (new
CCodeIdentifier (value_name
), value_type
))));
943 write_expression (cwhilefragment
, key_type
, new
CCodeIdentifier (entryiter_name
), new
CCodeIdentifier ("_key"));
944 write_expression (cwhilefragment
, value_type
, new
CCodeIdentifier (entryiter_name
), new
CCodeIdentifier ("_value"));
946 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
947 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
948 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (entryiter_name
)));
949 cwhilefragment
.append (new
CCodeExpressionStatement (iter_call
));
951 fragment
.append (cwhile
);
953 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
954 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
955 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
956 fragment
.append (new
CCodeExpressionStatement (iter_call
));
959 public void write_expression (CCodeFragment fragment
, DataType type
, CCodeExpression iter_expr
, CCodeExpression expr
) {
960 BasicTypeInfo basic_type
;
961 if (is_string_marshalled_enum (type
.data_type
)) {
962 get_basic_type_info ("s", out basic_type
);
963 var result
= generate_enum_value_to_string (fragment
, type as EnumValueType
, expr
);
964 write_basic (fragment
, basic_type
, iter_expr
, result
);
965 } else if (get_basic_type_info (get_type_signature (type
), out basic_type
)) {
966 write_basic (fragment
, basic_type
, iter_expr
, expr
);
967 } else if (type is ArrayType
) {
968 write_array (fragment
, (ArrayType
) type
, iter_expr
, expr
);
969 } else if (type
.data_type is Struct
) {
972 st_expr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, st_expr
);
974 if (type
.data_type
.get_full_name () == "GLib.Value") {
975 write_value (fragment
, iter_expr
, st_expr
);
977 write_struct (fragment
, (Struct
) type
.data_type
, iter_expr
, st_expr
);
979 } else if (type is ObjectType
) {
980 if (type
.data_type
.get_full_name () == "GLib.HashTable") {
981 write_hash_table (fragment
, (ObjectType
) type
, iter_expr
, expr
);
984 Report
.error (type
.source_reference
, "D-Bus serialization of type `%s' is not supported".printf (type
.to_string ()));
988 public void add_dbus_helpers () {
989 if (cfile
.add_declaration ("_vala_dbus_register_object")) {
993 cfile
.add_include ("dbus/dbus.h");
994 cfile
.add_include ("dbus/dbus-glib.h");
995 cfile
.add_include ("dbus/dbus-glib-lowlevel.h");
997 var dbusvtable
= new
CCodeStruct ("_DBusObjectVTable");
998 dbusvtable
.add_field ("void", "(*register_object) (DBusConnection*, const char*, void*)");
999 cfile
.add_type_definition (dbusvtable
);
1001 cfile
.add_type_declaration (new
CCodeTypeDefinition ("struct _DBusObjectVTable", new
CCodeVariableDeclarator ("_DBusObjectVTable")));
1003 var cfunc
= new
CCodeFunction ("_vala_dbus_register_object", "void");
1004 cfunc
.add_parameter (new
CCodeParameter ("connection", "DBusConnection*"));
1005 cfunc
.add_parameter (new
CCodeParameter ("path", "const char*"));
1006 cfunc
.add_parameter (new
CCodeParameter ("object", "void*"));
1008 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
1009 cfile
.add_function_declaration (cfunc
);
1011 var block
= new
CCodeBlock ();
1012 cfunc
.block
= block
;
1014 var cdecl
= new
CCodeDeclaration ("const _DBusObjectVTable *");
1015 cdecl
.add_declarator (new
CCodeVariableDeclarator ("vtable"));
1016 block
.add_statement (cdecl
);
1018 var quark
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_quark_from_static_string"));
1019 quark
.add_argument (new
CCodeConstant ("\"DBusObjectVTable\""));
1021 var get_qdata
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_get_qdata"));
1022 get_qdata
.add_argument (new
CCodeIdentifier ("G_TYPE_FROM_INSTANCE (object)"));
1023 get_qdata
.add_argument (quark
);
1025 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("vtable"), get_qdata
)));
1027 var cregister
= new
CCodeFunctionCall (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("vtable"), "register_object"));
1028 cregister
.add_argument (new
CCodeIdentifier ("connection"));
1029 cregister
.add_argument (new
CCodeIdentifier ("path"));
1030 cregister
.add_argument (new
CCodeIdentifier ("object"));
1032 var ifblock
= new
CCodeBlock ();
1033 ifblock
.add_statement (new
CCodeExpressionStatement (cregister
));
1035 var elseblock
= new
CCodeBlock ();
1037 var warn
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_warning"));
1038 warn
.add_argument (new
CCodeConstant ("\"Object does not implement any D-Bus interface\""));
1040 elseblock
.add_statement (new
CCodeExpressionStatement(warn
));
1042 block
.add_statement (new
CCodeIfStatement (new
CCodeIdentifier ("vtable"), ifblock
, elseblock
));
1044 cfile
.add_function (cfunc
);
1046 // unregister function
1047 cfunc
= new
CCodeFunction ("_vala_dbus_unregister_object", "void");
1048 cfunc
.add_parameter (new
CCodeParameter ("connection", "gpointer"));
1049 cfunc
.add_parameter (new
CCodeParameter ("object", "GObject*"));
1051 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
1052 cfile
.add_function_declaration (cfunc
);
1054 block
= new
CCodeBlock ();
1055 cfunc
.block
= block
;
1057 cdecl
= new
CCodeDeclaration ("char*");
1058 cdecl
.add_declarator (new
CCodeVariableDeclarator ("path"));
1059 block
.add_statement (cdecl
);
1061 var path
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_steal_data"));
1062 path
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("object"), "GObject*"));
1063 path
.add_argument (new
CCodeConstant ("\"dbus_object_path\""));
1064 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("path"), path
)));
1066 var unregister_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_connection_unregister_object_path"));
1067 unregister_call
.add_argument (new
CCodeIdentifier ("connection"));
1068 unregister_call
.add_argument (new
CCodeIdentifier ("path"));
1069 block
.add_statement (new
CCodeExpressionStatement (unregister_call
));
1071 var path_free
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
1072 path_free
.add_argument (new
CCodeIdentifier ("path"));
1073 block
.add_statement (new
CCodeExpressionStatement (path_free
));
1075 cfile
.add_function (cfunc
);