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 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 public DBusModule (CCodeGenerator codegen
, CCodeModule? next
) {
52 bool get_basic_type_info (string signature
, out BasicTypeInfo basic_type
) {
53 foreach (BasicTypeInfo info
in basic_types
) {
54 if (info
.signature
== signature
) {
62 CCodeExpression?
get_array_length (CCodeExpression expr
, int dim
) {
63 var id
= expr as CCodeIdentifier
;
64 var ma
= expr as CCodeMemberAccess
;
66 return new
CCodeIdentifier ("%s_length%d".printf (id
.name
, dim
));
67 } else if (ma
!= null) {
68 return new CCodeMemberAccess
.pointer (ma
.inner
, "%s_length%d".printf (ma
.member_name
, dim
));
73 CCodeExpression
read_basic (CCodeFragment fragment
, BasicTypeInfo basic_type
, CCodeExpression iter_expr
) {
74 string temp_name
= "_tmp%d".printf (next_temp_var_id
++);
76 var cdecl
= new
CCodeDeclaration (basic_type
.cname
);
77 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
));
78 fragment
.append (cdecl
);
80 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_get_basic"));
81 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
82 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (temp_name
)));
83 fragment
.append (new
CCodeExpressionStatement (iter_call
));
85 var temp_result
= new
CCodeIdentifier (temp_name
);
87 if (basic_type
.signature
== "s"
88 || basic_type
.signature
== "o"
89 || basic_type
.signature
== "g") {
90 var dup_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strdup"));
91 dup_call
.add_argument (temp_result
);
98 CCodeExpression
read_array (CCodeFragment fragment
, ArrayType array_type
, CCodeExpression iter_expr
, CCodeExpression? expr
) {
99 string temp_name
= "_tmp%d".printf (next_temp_var_id
++);
101 var cdecl
= new
CCodeDeclaration (array_type
.get_cname ());
102 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
, new
CCodeConstant ("NULL")));
103 fragment
.append (cdecl
);
105 cdecl
= new
CCodeDeclaration ("int");
106 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
+ "_length", new
CCodeConstant ("0")));
107 fragment
.append (cdecl
);
109 cdecl
= new
CCodeDeclaration ("int");
110 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
+ "_size", new
CCodeConstant ("0")));
111 fragment
.append (cdecl
);
113 read_array_dim (fragment
, array_type
, 1, temp_name
, iter_expr
, expr
);
115 return new
CCodeIdentifier (temp_name
);
118 void read_array_dim (CCodeFragment fragment
, ArrayType array_type
, int dim
, string temp_name
, CCodeExpression iter_expr
, CCodeExpression? expr
) {
119 string subiter_name
= "_tmp%d".printf (next_temp_var_id
++);
121 var cdecl
= new
CCodeDeclaration ("int");
122 cdecl
.add_declarator (new
CCodeVariableDeclarator ("%s_length%d".printf (temp_name
, dim
), new
CCodeConstant ("0")));
123 fragment
.append (cdecl
);
125 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
126 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
127 fragment
.append (cdecl
);
129 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_recurse"));
130 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
131 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
132 fragment
.append (new
CCodeExpressionStatement (iter_call
));
134 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_get_arg_type"));
135 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
137 var cforblock
= new
CCodeBlock ();
138 var cforfragment
= new
CCodeFragment ();
139 cforblock
.add_statement (cforfragment
);
140 var cfor
= new
CCodeForStatement (iter_call
, cforblock
);
141 cfor
.add_iterator (new
CCodeUnaryExpression (CCodeUnaryOperator
.POSTFIX_INCREMENT
, new
CCodeIdentifier ("%s_length%d".printf (temp_name
, dim
))));
143 if (dim
< array_type
.rank
) {
144 read_array_dim (cforfragment
, array_type
, dim
+ 1, temp_name
, new
CCodeIdentifier (subiter_name
), expr
);
146 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_next"));
147 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
148 cforfragment
.append (new
CCodeExpressionStatement (iter_call
));
150 var size_check
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, new
CCodeIdentifier (temp_name
+ "_size"), new
CCodeIdentifier (temp_name
+ "_length"));
151 var renew_block
= new
CCodeBlock ();
153 // tmp_size = (tmp_size > 0) ? (2 * tmp_size) : 4;
154 var init_check
= new
CCodeBinaryExpression (CCodeBinaryOperator
.GREATER_THAN
, new
CCodeIdentifier (temp_name
+ "_size"), new
CCodeConstant ("0"));
155 var new_size
= new
CCodeConditionalExpression (init_check
, new
CCodeBinaryExpression (CCodeBinaryOperator
.MUL
, new
CCodeConstant ("2"), new
CCodeIdentifier (temp_name
+ "_size")), new
CCodeConstant ("4"));
156 renew_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier (temp_name
+ "_size"), new_size
)));
158 var renew_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_renew"));
159 renew_call
.add_argument (new
CCodeIdentifier (array_type
.element_type
.get_cname ()));
160 renew_call
.add_argument (new
CCodeIdentifier (temp_name
));
161 renew_call
.add_argument (new
CCodeIdentifier (temp_name
+ "_size"));
162 var renew_stmt
= new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier (temp_name
), renew_call
));
163 renew_block
.add_statement (renew_stmt
);
165 var cif
= new
CCodeIfStatement (size_check
, renew_block
);
166 cforfragment
.append (cif
);
168 var element_access
= new
CCodeElementAccess (new
CCodeIdentifier (temp_name
), new
CCodeUnaryExpression (CCodeUnaryOperator
.POSTFIX_INCREMENT
, new
CCodeIdentifier (temp_name
+ "_length")));
169 var element_expr
= read_expression (cforfragment
, array_type
.element_type
, new
CCodeIdentifier (subiter_name
), null);
170 cforfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (element_access
, element_expr
)));
173 fragment
.append (cfor
);
176 fragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (get_array_length (expr
, dim
), new
CCodeIdentifier ("%s_length%d".printf (temp_name
, dim
)))));
180 CCodeExpression
read_struct (CCodeFragment fragment
, Struct st
, CCodeExpression iter_expr
) {
181 string temp_name
= "_tmp%d".printf (next_temp_var_id
++);
182 string subiter_name
= "_tmp%d".printf (next_temp_var_id
++);
184 var cdecl
= new
CCodeDeclaration (st
.get_cname ());
185 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
));
186 fragment
.append (cdecl
);
188 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
189 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
190 fragment
.append (cdecl
);
192 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_recurse"));
193 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
194 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
195 fragment
.append (new
CCodeExpressionStatement (iter_call
));
197 foreach (Field f
in st
.get_fields ()) {
198 if (f
.binding
!= MemberBinding
.INSTANCE
) {
202 var field_expr
= read_expression (fragment
, f
.field_type
, new
CCodeIdentifier (subiter_name
), new
CCodeMemberAccess (new
CCodeIdentifier (temp_name
), f
.get_cname ()));
203 fragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeMemberAccess (new
CCodeIdentifier (temp_name
), f
.get_cname ()), field_expr
)));
206 return new
CCodeIdentifier (temp_name
);
209 CCodeExpression
read_value (CCodeFragment fragment
, CCodeExpression iter_expr
) {
210 string temp_name
= "_tmp%d".printf (next_temp_var_id
++);
211 string subiter_name
= "_tmp%d".printf (next_temp_var_id
++);
213 // 0-initialize struct with struct initializer { 0 }
214 var cvalinit
= new
CCodeInitializerList ();
215 cvalinit
.append (new
CCodeConstant ("0"));
217 var cdecl
= new
CCodeDeclaration ("GValue");
218 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
, cvalinit
));
219 fragment
.append (cdecl
);
221 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
222 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
223 fragment
.append (cdecl
);
225 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_recurse"));
226 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
227 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
228 fragment
.append (new
CCodeExpressionStatement (iter_call
));
230 CCodeIfStatement clastif
= null;
232 foreach (BasicTypeInfo basic_type
in basic_types
) {
233 var type_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_get_arg_type"));
234 type_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
235 var type_check
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, type_call
, new
CCodeIdentifier ("DBUS_TYPE_" + basic_type
.type_name
));
237 var type_block
= new
CCodeBlock ();
238 var type_fragment
= new
CCodeFragment ();
239 type_block
.add_statement (type_fragment
);
240 var result
= read_basic (type_fragment
, basic_type
, new
CCodeIdentifier (subiter_name
));
242 var value_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_init"));
243 value_init
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (temp_name
)));
244 value_init
.add_argument (new
CCodeIdentifier (basic_type
.gtype
));
245 type_fragment
.append (new
CCodeExpressionStatement (value_init
));
247 var value_set
= new
CCodeFunctionCall (new
CCodeIdentifier (basic_type
.set_value_function
));
248 value_set
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (temp_name
)));
249 value_set
.add_argument (result
);
250 type_fragment
.append (new
CCodeExpressionStatement (value_set
));
252 var cif
= new
CCodeIfStatement (type_check
, type_block
);
253 if (clastif
== null) {
254 fragment
.append (cif
);
256 clastif
.false_statement
= cif
;
262 return new
CCodeIdentifier (temp_name
);
265 CCodeExpression
read_hash_table (CCodeFragment fragment
, ObjectType type
, CCodeExpression iter_expr
) {
266 string temp_name
= "_tmp%d".printf (next_temp_var_id
++);
267 string subiter_name
= "_tmp%d".printf (next_temp_var_id
++);
268 string entryiter_name
= "_tmp%d".printf (next_temp_var_id
++);
270 var type_args
= type
.get_type_arguments ();
271 assert (type_args
.size
== 2);
272 var key_type
= type_args
.get (0);
273 var value_type
= type_args
.get (1);
275 var cdecl
= new
CCodeDeclaration ("GHashTable*");
276 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
));
277 fragment
.append (cdecl
);
279 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
280 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
281 fragment
.append (cdecl
);
283 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
284 cdecl
.add_declarator (new
CCodeVariableDeclarator (entryiter_name
));
285 fragment
.append (cdecl
);
287 var hash_table_new
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_hash_table_new_full"));
288 if (key_type
.data_type
== string_type
.data_type
) {
289 hash_table_new
.add_argument (new
CCodeIdentifier ("g_str_hash"));
290 hash_table_new
.add_argument (new
CCodeIdentifier ("g_str_equal"));
292 hash_table_new
.add_argument (new
CCodeIdentifier ("g_direct_hash"));
293 hash_table_new
.add_argument (new
CCodeIdentifier ("g_direct_equal"));
295 if (key_type
.data_type
== string_type
.data_type
) {
296 hash_table_new
.add_argument (new
CCodeIdentifier ("g_free"));
298 hash_table_new
.add_argument (new
CCodeIdentifier ("NULL"));
300 if (value_type
.data_type
== string_type
.data_type
) {
301 hash_table_new
.add_argument (new
CCodeIdentifier ("g_free"));
303 hash_table_new
.add_argument (new
CCodeIdentifier ("NULL"));
305 fragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier (temp_name
), hash_table_new
)));
307 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_recurse"));
308 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
309 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
310 fragment
.append (new
CCodeExpressionStatement (iter_call
));
312 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_get_arg_type"));
313 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
315 var cwhileblock
= new
CCodeBlock ();
316 var cwhilefragment
= new
CCodeFragment ();
317 cwhileblock
.add_statement (cwhilefragment
);
318 var cwhile
= new
CCodeWhileStatement (iter_call
, cwhileblock
);
320 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_recurse"));
321 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
322 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (entryiter_name
)));
323 cwhilefragment
.append (new
CCodeExpressionStatement (iter_call
));
325 cdecl
= new
CCodeDeclaration (key_type
.get_cname ());
326 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_key"));
327 cwhilefragment
.append (cdecl
);
329 cdecl
= new
CCodeDeclaration (value_type
.get_cname ());
330 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_value"));
331 cwhilefragment
.append (cdecl
);
333 var key_expr
= read_expression (cwhilefragment
, key_type
, new
CCodeIdentifier (entryiter_name
), null);
334 cwhilefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_key"), key_expr
)));
336 var value_expr
= read_expression (cwhilefragment
, value_type
, new
CCodeIdentifier (entryiter_name
), null);
337 cwhilefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_value"), value_expr
)));
339 var hash_table_insert
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_hash_table_insert"));
340 hash_table_insert
.add_argument (new
CCodeIdentifier (temp_name
));
341 hash_table_insert
.add_argument (convert_to_generic_pointer (new
CCodeIdentifier ("_key"), key_type
));
342 hash_table_insert
.add_argument (convert_to_generic_pointer (new
CCodeIdentifier ("_value"), value_type
));
343 cwhilefragment
.append (new
CCodeExpressionStatement (hash_table_insert
));
345 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_next"));
346 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
347 cwhilefragment
.append (new
CCodeExpressionStatement (iter_call
));
349 fragment
.append (cwhile
);
351 return new
CCodeIdentifier (temp_name
);
354 public CCodeExpression?
read_expression (CCodeFragment fragment
, DataType type
, CCodeExpression iter_expr
, CCodeExpression? expr
) {
355 BasicTypeInfo basic_type
;
356 CCodeExpression result
= null;
357 if (get_basic_type_info (type
.get_type_signature (), out basic_type
)) {
358 result
= read_basic (fragment
, basic_type
, iter_expr
);
359 } else if (type is ArrayType
) {
360 result
= read_array (fragment
, (ArrayType
) type
, iter_expr
, expr
);
361 } else if (type
.data_type is Struct
) {
362 var st
= (Struct
) type
.data_type
;
363 if (type
.data_type
.get_full_name () == "GLib.Value") {
364 result
= read_value (fragment
, iter_expr
);
366 result
= read_struct (fragment
, st
, iter_expr
);
369 var csizeof
= new
CCodeFunctionCall (new
CCodeIdentifier ("sizeof"));
370 csizeof
.add_argument (new
CCodeIdentifier (st
.get_cname ()));
371 var cdup
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_memdup"));
372 cdup
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, result
));
373 cdup
.add_argument (csizeof
);
376 } else if (type is ObjectType
) {
377 if (type
.data_type
.get_full_name () == "GLib.HashTable") {
378 result
= read_hash_table (fragment
, (ObjectType
) type
, iter_expr
);
381 Report
.error (type
.source_reference
, "D-Bus deserialization of type `%s' is not supported".printf (type
.to_string ()));
385 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_next"));
386 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
387 fragment
.append (new
CCodeExpressionStatement (iter_call
));
392 void write_basic (CCodeFragment fragment
, BasicTypeInfo basic_type
, CCodeExpression iter_expr
, CCodeExpression expr
) {
393 string temp_name
= "_tmp%d".printf (next_temp_var_id
++);
395 var cdecl
= new
CCodeDeclaration (basic_type
.cname
);
396 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
));
397 fragment
.append (cdecl
);
399 fragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier (temp_name
), expr
)));
401 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_append_basic"));
402 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
403 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_" + basic_type
.type_name
));
404 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (temp_name
)));
405 fragment
.append (new
CCodeExpressionStatement (iter_call
));
408 void write_array (CCodeFragment fragment
, ArrayType array_type
, CCodeExpression iter_expr
, CCodeExpression array_expr
) {
409 string array_iter_name
= "_tmp%d".printf (next_temp_var_id
++);
411 var cdecl
= new
CCodeDeclaration (array_type
.get_cname ());
412 cdecl
.add_declarator (new
CCodeVariableDeclarator (array_iter_name
));
413 fragment
.append (cdecl
);
415 fragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier (array_iter_name
), array_expr
)));
417 write_array_dim (fragment
, array_type
, 1, iter_expr
, array_expr
, new
CCodeIdentifier (array_iter_name
));
420 void write_array_dim (CCodeFragment fragment
, ArrayType array_type
, int dim
, CCodeExpression iter_expr
, CCodeExpression array_expr
, CCodeExpression array_iter_expr
) {
421 string subiter_name
= "_tmp%d".printf (next_temp_var_id
++);
422 string index_name
= "_tmp%d".printf (next_temp_var_id
++);
424 var cdecl
= new
CCodeDeclaration ("DBusMessageIter");
425 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
426 fragment
.append (cdecl
);
428 cdecl
= new
CCodeDeclaration ("int");
429 cdecl
.add_declarator (new
CCodeVariableDeclarator (index_name
));
430 fragment
.append (cdecl
);
432 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
433 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
434 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_ARRAY"));
435 iter_call
.add_argument (new
CCodeConstant ("\"%s%s\"".printf (string.nfill (array_type
.rank
- dim
, 'a'), array_type
.element_type
.get_type_signature ())));
436 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
437 fragment
.append (new
CCodeExpressionStatement (iter_call
));
439 var cforblock
= new
CCodeBlock ();
440 var cforfragment
= new
CCodeFragment ();
441 cforblock
.add_statement (cforfragment
);
442 var cfor
= new
CCodeForStatement (new
CCodeBinaryExpression (CCodeBinaryOperator
.LESS_THAN
, new
CCodeIdentifier (index_name
), get_array_length (array_expr
, dim
)), cforblock
);
443 cfor
.add_initializer (new
CCodeAssignment (new
CCodeIdentifier (index_name
), new
CCodeConstant ("0")));
444 cfor
.add_iterator (new
CCodeUnaryExpression (CCodeUnaryOperator
.POSTFIX_INCREMENT
, new
CCodeIdentifier (index_name
)));
446 if (dim
< array_type
.rank
) {
447 write_array_dim (cforfragment
, array_type
, dim
+ 1, new
CCodeIdentifier (subiter_name
), array_expr
, array_iter_expr
);
449 var array_iter_incr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POSTFIX_INCREMENT
, array_iter_expr
);
450 var element_expr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, array_iter_incr
);
451 write_expression (cforfragment
, array_type
.element_type
, new
CCodeIdentifier (subiter_name
), element_expr
);
453 fragment
.append (cfor
);
455 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
456 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
457 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
458 fragment
.append (new
CCodeExpressionStatement (iter_call
));
461 void write_struct (CCodeFragment fragment
, Struct st
, CCodeExpression iter_expr
, CCodeExpression struct_expr
) {
462 string subiter_name
= "_tmp%d".printf (next_temp_var_id
++);
464 var cdecl
= new
CCodeDeclaration ("DBusMessageIter");
465 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
466 fragment
.append (cdecl
);
468 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
469 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
470 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_STRUCT"));
471 iter_call
.add_argument (new
CCodeConstant ("NULL"));
472 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
473 fragment
.append (new
CCodeExpressionStatement (iter_call
));
475 foreach (Field f
in st
.get_fields ()) {
476 if (f
.binding
!= MemberBinding
.INSTANCE
) {
480 write_expression (fragment
, f
.field_type
, new
CCodeIdentifier (subiter_name
), new
CCodeMemberAccess (struct_expr
, f
.get_cname ()));
483 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
484 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
485 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
486 fragment
.append (new
CCodeExpressionStatement (iter_call
));
489 void write_value (CCodeFragment fragment
, CCodeExpression iter_expr
, CCodeExpression expr
) {
490 string subiter_name
= "_tmp%d".printf (next_temp_var_id
++);
492 var cdecl
= new
CCodeDeclaration ("DBusMessageIter");
493 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
494 fragment
.append (cdecl
);
496 CCodeIfStatement clastif
= null;
498 foreach (BasicTypeInfo basic_type
in basic_types
) {
499 // ensure that there is only one case per GType
500 if (basic_type
.get_value_function
== null) {
504 var type_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE"));
505 type_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, expr
));
506 var type_check
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, type_call
, new
CCodeIdentifier (basic_type
.gtype
));
508 var type_block
= new
CCodeBlock ();
509 var type_fragment
= new
CCodeFragment ();
510 type_block
.add_statement (type_fragment
);
512 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
513 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
514 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_VARIANT"));
515 iter_call
.add_argument (new
CCodeConstant ("\"%s\"".printf (basic_type
.signature
)));
516 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
517 type_fragment
.append (new
CCodeExpressionStatement (iter_call
));
519 var value_get
= new
CCodeFunctionCall (new
CCodeIdentifier (basic_type
.get_value_function
));
520 value_get
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, expr
));
522 write_basic (type_fragment
, basic_type
, new
CCodeIdentifier (subiter_name
), value_get
);
524 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
525 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
526 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
527 type_fragment
.append (new
CCodeExpressionStatement (iter_call
));
529 var cif
= new
CCodeIfStatement (type_check
, type_block
);
530 if (clastif
== null) {
531 fragment
.append (cif
);
533 clastif
.false_statement
= cif
;
540 void write_hash_table (CCodeFragment fragment
, ObjectType type
, CCodeExpression iter_expr
, CCodeExpression hash_table_expr
) {
541 string subiter_name
= "_tmp%d".printf (next_temp_var_id
++);
542 string entryiter_name
= "_tmp%d".printf (next_temp_var_id
++);
543 string tableiter_name
= "_tmp%d".printf (next_temp_var_id
++);
544 string key_name
= "_tmp%d".printf (next_temp_var_id
++);
545 string value_name
= "_tmp%d".printf (next_temp_var_id
++);
547 var type_args
= type
.get_type_arguments ();
548 assert (type_args
.size
== 2);
549 var key_type
= type_args
.get (0);
550 var value_type
= type_args
.get (1);
552 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
553 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
554 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_ARRAY"));
555 iter_call
.add_argument (new
CCodeConstant ("\"{%s%s}\"".printf (key_type
.get_type_signature (), value_type
.get_type_signature ())));
556 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
557 fragment
.append (new
CCodeExpressionStatement (iter_call
));
559 var cdecl
= new
CCodeDeclaration ("DBusMessageIter");
560 cdecl
.add_declarator (new
CCodeVariableDeclarator (subiter_name
));
561 cdecl
.add_declarator (new
CCodeVariableDeclarator (entryiter_name
));
562 fragment
.append (cdecl
);
564 cdecl
= new
CCodeDeclaration ("GHashTableIter");
565 cdecl
.add_declarator (new
CCodeVariableDeclarator (tableiter_name
));
566 fragment
.append (cdecl
);
568 cdecl
= new
CCodeDeclaration ("gpointer");
569 cdecl
.add_declarator (new
CCodeVariableDeclarator (key_name
));
570 cdecl
.add_declarator (new
CCodeVariableDeclarator (value_name
));
571 fragment
.append (cdecl
);
573 var iter_init_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_hash_table_iter_init"));
574 iter_init_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (tableiter_name
)));
575 iter_init_call
.add_argument (hash_table_expr
);
576 fragment
.append (new
CCodeExpressionStatement (iter_init_call
));
578 var iter_next_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_hash_table_iter_next"));
579 iter_next_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (tableiter_name
)));
580 iter_next_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (key_name
)));
581 iter_next_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (value_name
)));
583 var cwhileblock
= new
CCodeBlock ();
584 var cwhilefragment
= new
CCodeFragment ();
585 cwhileblock
.add_statement (cwhilefragment
);
586 var cwhile
= new
CCodeWhileStatement (iter_next_call
, cwhileblock
);
588 cdecl
= new
CCodeDeclaration (key_type
.get_cname ());
589 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_key"));
590 cwhilefragment
.append (cdecl
);
592 cdecl
= new
CCodeDeclaration (value_type
.get_cname ());
593 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_value"));
594 cwhilefragment
.append (cdecl
);
596 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
597 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
598 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_DICT_ENTRY"));
599 iter_call
.add_argument (new
CCodeConstant ("NULL"));
600 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (entryiter_name
)));
601 cwhilefragment
.append (new
CCodeExpressionStatement (iter_call
));
603 cwhilefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_key"), convert_from_generic_pointer (new
CCodeIdentifier (key_name
), key_type
))));
604 cwhilefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_value"), convert_from_generic_pointer (new
CCodeIdentifier (value_name
), value_type
))));
606 write_expression (cwhilefragment
, key_type
, new
CCodeIdentifier (entryiter_name
), new
CCodeIdentifier ("_key"));
607 write_expression (cwhilefragment
, value_type
, new
CCodeIdentifier (entryiter_name
), new
CCodeIdentifier ("_value"));
609 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
610 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
611 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (entryiter_name
)));
612 cwhilefragment
.append (new
CCodeExpressionStatement (iter_call
));
614 fragment
.append (cwhile
);
616 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
617 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, iter_expr
));
618 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (subiter_name
)));
619 fragment
.append (new
CCodeExpressionStatement (iter_call
));
622 public void write_expression (CCodeFragment fragment
, DataType type
, CCodeExpression iter_expr
, CCodeExpression expr
) {
623 BasicTypeInfo basic_type
;
624 if (get_basic_type_info (type
.get_type_signature (), out basic_type
)) {
625 write_basic (fragment
, basic_type
, iter_expr
, expr
);
626 } else if (type is ArrayType
) {
627 write_array (fragment
, (ArrayType
) type
, iter_expr
, expr
);
628 } else if (type
.data_type is Struct
) {
631 st_expr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, st_expr
);
633 if (type
.data_type
.get_full_name () == "GLib.Value") {
634 write_value (fragment
, iter_expr
, st_expr
);
636 write_struct (fragment
, (Struct
) type
.data_type
, iter_expr
, st_expr
);
638 } else if (type is ObjectType
) {
639 if (type
.data_type
.get_full_name () == "GLib.HashTable") {
640 write_hash_table (fragment
, (ObjectType
) type
, iter_expr
, expr
);
643 Report
.error (type
.source_reference
, "D-Bus serialization of type `%s' is not supported".printf (type
.to_string ()));