Line data Source code
1 : /* valagvariantmodule.vala
2 : *
3 : * Copyright (C) 2010-2011 Jürg Billeter
4 : *
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.
9 :
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.
14 :
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
18 : *
19 : * Author:
20 : * Jürg Billeter <j@bitron.ch>
21 : */
22 :
23 4371 : public class Vala.GVariantModule : GValueModule {
24 : struct BasicTypeInfo {
25 : public unowned string signature;
26 : public unowned string type_name;
27 : public bool is_string;
28 : }
29 :
30 : const BasicTypeInfo[] basic_types = {
31 : { "y", "byte", false },
32 : { "b", "boolean", false },
33 : { "n", "int16", false },
34 : { "q", "uint16", false },
35 : { "i", "int32", false },
36 : { "u", "uint32", false },
37 : { "x", "int64", false },
38 : { "t", "uint64", false },
39 : { "d", "double", false },
40 : { "s", "string", true },
41 : { "o", "object_path", true },
42 : { "g", "signature", true }
43 : };
44 :
45 : static bool is_string_marshalled_enum (TypeSymbol? symbol) {
46 751 : if (symbol != null && symbol is Enum) {
47 260 : return symbol.get_attribute_bool ("DBus", "use_string_marshalling");
48 : }
49 751 : return false;
50 : }
51 :
52 2 : string get_dbus_value (EnumValue value, string default_value) {
53 2 : var dbus_value = value.get_attribute_string ("DBus", "value");
54 2 : if (dbus_value != null) {
55 2 : return dbus_value;;
56 : }
57 4 : return default_value;
58 : }
59 :
60 306 : public static string? get_dbus_signature (Symbol symbol) {
61 306 : return symbol.get_attribute_string ("DBus", "signature");
62 : }
63 :
64 513 : bool get_basic_type_info (string? signature, out BasicTypeInfo basic_type) {
65 513 : if (signature != null) {
66 4625 : foreach (BasicTypeInfo info in basic_types) {
67 4500 : if (info.signature == signature) {
68 385 : basic_type = info;
69 385 : return true;
70 : }
71 : }
72 : }
73 128 : basic_type = BasicTypeInfo ();
74 128 : return false;
75 : }
76 :
77 80 : public override void visit_enum (Enum en) {
78 80 : base.visit_enum (en);
79 :
80 80 : if (is_string_marshalled_enum (en)) {
81 : // strcmp
82 1 : cfile.add_include ("string.h");
83 :
84 : // for G_DBUS_ERROR
85 1 : cfile.add_include ("gio/gio.h");
86 :
87 1 : cfile.add_function (generate_enum_from_string_function (en));
88 1 : cfile.add_function (generate_enum_to_string_function (en));
89 : }
90 : }
91 :
92 3836 : public override bool generate_enum_declaration (Enum en, CCodeFile decl_space) {
93 3836 : if (base.generate_enum_declaration (en, decl_space)) {
94 168 : if (is_string_marshalled_enum (en)) {
95 3 : decl_space.add_function_declaration (generate_enum_from_string_function_declaration (en));
96 3 : decl_space.add_function_declaration (generate_enum_to_string_function_declaration (en));
97 : }
98 168 : return true;
99 : }
100 3836 : return false;
101 : }
102 :
103 1457 : int next_variant_function_id = 0;
104 :
105 1880 : public override void visit_cast_expression (CastExpression expr) {
106 1905 : var value = expr.inner.target_value;
107 1825 : var target_type = expr.type_reference;
108 :
109 1813 : if (expr.is_non_null_cast || value.value_type == null || gvariant_type == null || value.value_type.type_symbol != gvariant_type) {
110 1746 : base.visit_cast_expression (expr);
111 1746 : return;
112 : }
113 :
114 67 : generate_type_declaration (expr.type_reference, cfile);
115 :
116 67 : string variant_func = "_variant_get%d".printf (++next_variant_function_id);
117 :
118 67 : var variant = value;
119 92 : if (value.value_type.value_owned) {
120 : // value leaked, destroy it
121 25 : var temp_value = store_temp_value (value, expr);
122 25 : temp_ref_values.insert (0, ((GLibValue) temp_value).copy ());
123 50 : variant = temp_value;
124 : }
125 :
126 67 : var ccall = new CCodeFunctionCall (new CCodeIdentifier (variant_func));
127 67 : ccall.add_argument (get_cvalue_ (variant));
128 :
129 67 : var needs_init = (target_type is ArrayType);
130 67 : var result = create_temp_value (target_type, needs_init, expr);
131 :
132 67 : var cfunc = new CCodeFunction (variant_func);
133 67 : cfunc.modifiers = CCodeModifiers.STATIC;
134 67 : cfunc.add_parameter (new CCodeParameter ("value", "GVariant*"));
135 :
136 67 : if (!target_type.is_real_non_null_struct_type ()) {
137 64 : cfunc.return_type = get_ccode_name (target_type);
138 : }
139 :
140 67 : if (target_type.is_real_non_null_struct_type ()) {
141 : // structs are returned via out parameter
142 3 : cfunc.add_parameter (new CCodeParameter ("result", "%s *".printf (get_ccode_name (target_type))));
143 3 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue_ (result)));
144 75 : } else if (target_type is ArrayType) {
145 : // return array length if appropriate
146 : // tmp = _variant_get (variant, &tmp_length);
147 11 : unowned ArrayType array_type = (ArrayType) target_type;
148 11 : var length_ctype = get_ccode_array_length_type (array_type);
149 26 : for (int dim = 1; dim <= array_type.rank; dim++) {
150 15 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_array_length_cvalue (result, dim)));
151 15 : cfunc.add_parameter (new CCodeParameter (get_array_length_cname ("result", dim), length_ctype + "*"));
152 : }
153 : }
154 :
155 67 : if (!target_type.is_real_non_null_struct_type ()) {
156 64 : ccode.add_assignment (get_cvalue_ (result), ccall);
157 : } else {
158 3 : ccode.add_expression (ccall);
159 : }
160 :
161 67 : push_context (new EmitContext ());
162 67 : push_function (cfunc);
163 :
164 67 : CCodeExpression type_expr = null;
165 67 : BasicTypeInfo basic_type = {};
166 67 : bool is_basic_type = false;
167 77 : if (expr.is_silent_cast) {
168 10 : var signature = target_type.get_type_signature ();
169 10 : is_basic_type = get_basic_type_info (signature, out basic_type);
170 10 : var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_is_of_type"));
171 10 : ccheck.add_argument (new CCodeIdentifier ("value"));
172 14 : if (is_basic_type) {
173 6 : type_expr = new CCodeIdentifier ("G_VARIANT_TYPE_" + basic_type.type_name.ascii_up ());
174 : } else {
175 4 : var gvariant_type_type = new ObjectType ((Class) root_symbol.scope.lookup ("GLib").scope.lookup ("VariantType"));
176 4 : var type_temp = get_temp_variable (gvariant_type_type, true, expr, true);
177 4 : emit_temp_var (type_temp);
178 4 : type_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_type_new"));
179 4 : ((CCodeFunctionCall) type_expr).add_argument (new CCodeIdentifier ("\"%s\"".printf (signature)));
180 4 : store_value (get_local_cvalue (type_temp), new GLibValue (gvariant_type_type, type_expr), expr.source_reference);
181 4 : type_expr = get_variable_cexpression (type_temp.name);
182 : }
183 10 : ccheck.add_argument (type_expr);
184 10 : ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.AND, new CCodeIdentifier ("value"), ccheck));
185 : }
186 :
187 67 : CCodeExpression func_result = deserialize_expression (target_type, new CCodeIdentifier ("value"), new CCodeIdentifier ("*result"));
188 :
189 67 : if (expr.is_silent_cast) {
190 19 : if (is_basic_type && basic_type.is_string) {
191 1 : ccode.add_return (func_result);
192 : } else {
193 13 : if (!is_basic_type) {
194 4 : var type_free = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_type_free"));
195 4 : type_free.add_argument (type_expr);
196 4 : ccode.add_expression (type_free);
197 : }
198 9 : var temp_type = expr.target_type.copy ();
199 9 : if (!expr.target_type.is_real_struct_type ()) {
200 8 : temp_type.nullable = false;
201 : }
202 9 : var temp_value = create_temp_value (temp_type, false, expr);
203 9 : store_value (temp_value, new GLibValue (temp_type, func_result), expr.source_reference);
204 9 : ccode.add_return (get_cvalue_ (transform_value (temp_value, expr.target_type, expr)));
205 : }
206 10 : ccode.add_else ();
207 14 : if (!is_basic_type) {
208 4 : var type_free = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_type_free"));
209 4 : type_free.add_argument (type_expr);
210 4 : ccode.add_expression (type_free);
211 : }
212 10 : ccode.add_return (new CCodeConstant ("NULL"));
213 10 : ccode.close ();
214 57 : } else if (target_type.is_real_non_null_struct_type ()) {
215 3 : ccode.add_assignment (new CCodeIdentifier ("*result"), func_result);
216 : } else {
217 54 : ccode.add_return (func_result);
218 : }
219 :
220 67 : pop_function ();
221 67 : pop_context ();
222 :
223 67 : cfile.add_function_declaration (cfunc);
224 67 : cfile.add_function (cfunc);
225 :
226 67 : expr.target_value = load_temp_value (result);
227 : }
228 :
229 89 : CCodeExpression? get_array_length (CCodeExpression expr, int dim) {
230 297 : var id = expr as CCodeIdentifier;
231 89 : var ma = expr as CCodeMemberAccess;
232 89 : if (id != null) {
233 87 : return new CCodeIdentifier ("%s_length%d".printf (id.name, dim));
234 2 : } else if (ma != null) {
235 2 : if (ma.is_pointer) {
236 2 : return new CCodeMemberAccess.pointer (ma.inner, "%s_length%d".printf (ma.member_name, dim));
237 : } else {
238 0 : return new CCodeMemberAccess (ma.inner, "%s_length%d".printf (ma.member_name, dim));
239 : }
240 : } else {
241 : // must be NULL-terminated
242 0 : var len_call = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length"));
243 0 : len_call.add_argument (expr);
244 0 : return len_call;
245 : }
246 : }
247 :
248 6 : CCodeExpression? generate_enum_value_from_string (EnumValueType type, CCodeExpression? expr, CCodeExpression? error_expr) {
249 6 : var en = type.type_symbol as Enum;
250 6 : var from_string_name = "%s_from_string".printf (get_ccode_lower_case_name (en, null));
251 :
252 6 : var from_string_call = new CCodeFunctionCall (new CCodeIdentifier (from_string_name));
253 6 : from_string_call.add_argument (expr);
254 6 : from_string_call.add_argument (error_expr != null ? error_expr : new CCodeConstant ("NULL"));
255 :
256 6 : return from_string_call;
257 : }
258 :
259 3 : public CCodeFunction generate_enum_from_string_function_declaration (Enum en) {
260 3 : var from_string_name = "%s_from_string".printf (get_ccode_lower_case_name (en, null));
261 :
262 3 : var from_string_func = new CCodeFunction (from_string_name, get_ccode_name (en));
263 3 : from_string_func.add_parameter (new CCodeParameter ("str", "const char*"));
264 3 : from_string_func.add_parameter (new CCodeParameter ("error", "GError**"));
265 3 : from_string_func.modifiers |= CCodeModifiers.EXTERN;
266 3 : requires_vala_extern = true;
267 :
268 3 : return from_string_func;
269 : }
270 :
271 1 : public CCodeFunction generate_enum_from_string_function (Enum en) {
272 1 : var from_string_name = "%s_from_string".printf (get_ccode_lower_case_name (en, null));
273 :
274 1 : var from_string_func = new CCodeFunction (from_string_name, get_ccode_name (en));
275 1 : from_string_func.add_parameter (new CCodeParameter ("str", "const char*"));
276 1 : from_string_func.add_parameter (new CCodeParameter ("error", "GError**"));
277 :
278 1 : push_function (from_string_func);
279 :
280 1 : ccode.add_declaration (get_ccode_name (en), new CCodeVariableDeclarator.zero ("value", new CCodeConstant ("0")));
281 :
282 1 : bool firstif = true;
283 3 : foreach (EnumValue enum_value in en.get_values ()) {
284 1 : string dbus_value = get_dbus_value (enum_value, enum_value.name);
285 1 : var string_comparison = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
286 1 : string_comparison.add_argument (new CCodeIdentifier ("str"));
287 1 : string_comparison.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_value)));
288 1 : var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, string_comparison, new CCodeConstant ("0"));
289 1 : if (firstif) {
290 1 : ccode.open_if (cond);
291 1 : firstif = false;
292 : } else {
293 0 : ccode.else_if (cond);
294 : }
295 1 : ccode.add_assignment (new CCodeIdentifier ("value"), new CCodeIdentifier (get_ccode_name (enum_value)));
296 : }
297 :
298 1 : ccode.add_else ();
299 1 : var set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error"));
300 1 : set_error.add_argument (new CCodeIdentifier ("error"));
301 1 : set_error.add_argument (new CCodeIdentifier ("G_DBUS_ERROR"));
302 1 : set_error.add_argument (new CCodeIdentifier ("G_DBUS_ERROR_INVALID_ARGS"));
303 1 : set_error.add_argument (new CCodeConstant ("\"Invalid value for enum `%s'\"".printf (get_ccode_name (en))));
304 1 : ccode.add_expression (set_error);
305 1 : ccode.close ();
306 :
307 1 : ccode.add_return (new CCodeIdentifier ("value"));
308 :
309 1 : pop_function ();
310 1 : return from_string_func;
311 : }
312 :
313 185 : CCodeExpression deserialize_basic (BasicTypeInfo basic_type, CCodeExpression variant_expr, bool transfer = false) {
314 185 : var get_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get_" + basic_type.type_name));
315 185 : get_call.add_argument (variant_expr);
316 :
317 185 : if (basic_type.is_string) {
318 85 : if (transfer) {
319 6 : get_call.call = new CCodeIdentifier ("g_variant_get_string");
320 : } else {
321 79 : get_call.call = new CCodeIdentifier ("g_variant_dup_string");
322 : }
323 85 : get_call.add_argument (new CCodeConstant ("NULL"));
324 : }
325 :
326 : return get_call;
327 : }
328 :
329 32 : CCodeExpression deserialize_array (ArrayType array_type, CCodeExpression variant_expr, CCodeExpression? expr) {
330 32 : if (array_type.rank == 1 && array_type.get_type_signature () == "ay") {
331 2 : return deserialize_buffer_array (array_type, variant_expr, expr);
332 : }
333 :
334 30 : string temp_name = "_tmp%d_".printf (next_temp_var_id++);
335 :
336 30 : var new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_new"));
337 30 : new_call.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type)));
338 : // add one extra element for NULL-termination
339 30 : new_call.add_argument (new CCodeConstant ("5"));
340 :
341 30 : var length_ctype = get_ccode_array_length_type (array_type);
342 30 : ccode.add_declaration (get_ccode_name (array_type), new CCodeVariableDeclarator (temp_name, new_call));
343 30 : ccode.add_declaration (length_ctype, new CCodeVariableDeclarator (temp_name + "_length", new CCodeConstant ("0")));
344 30 : ccode.add_declaration (length_ctype, new CCodeVariableDeclarator (temp_name + "_size", new CCodeConstant ("4")));
345 :
346 30 : deserialize_array_dim (array_type, 1, temp_name, variant_expr, expr);
347 :
348 52 : if (array_type.element_type.is_reference_type_or_type_parameter ()) {
349 : // NULL terminate array
350 22 : var length = new CCodeIdentifier (temp_name + "_length");
351 22 : var element_access = new CCodeElementAccess (new CCodeIdentifier (temp_name), length);
352 22 : ccode.add_assignment (element_access, new CCodeConstant ("NULL"));
353 : }
354 :
355 30 : return new CCodeIdentifier (temp_name);
356 : }
357 :
358 74 : void deserialize_array_dim (ArrayType array_type, int dim, string temp_name, CCodeExpression variant_expr, CCodeExpression? expr) {
359 37 : string subiter_name = "_tmp%d_".printf (next_temp_var_id++);
360 37 : string element_name = "_tmp%d_".printf (next_temp_var_id++);
361 :
362 37 : ccode.add_declaration (get_ccode_array_length_type (array_type), new CCodeVariableDeclarator ("%s_length%d".printf (temp_name, dim), new CCodeConstant ("0")));
363 37 : ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator (subiter_name));
364 37 : ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator (element_name));
365 :
366 37 : var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
367 37 : iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name)));
368 37 : iter_call.add_argument (variant_expr);
369 37 : ccode.add_expression (iter_call);
370 :
371 37 : iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_next_value"));
372 37 : iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name)));
373 :
374 37 : var cforcond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeAssignment (new CCodeIdentifier (element_name), iter_call), new CCodeConstant ("NULL"));
375 37 : var cforiter = new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("%s_length%d".printf (temp_name, dim)));
376 37 : ccode.open_for (null, cforcond, cforiter);
377 :
378 67 : if (dim < array_type.rank) {
379 7 : deserialize_array_dim (array_type, dim + 1, temp_name, new CCodeIdentifier (element_name), expr);
380 : } else {
381 30 : var size_check = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier (temp_name + "_size"), new CCodeIdentifier (temp_name + "_length"));
382 :
383 30 : ccode.open_if (size_check);
384 :
385 : // tmp_size = (2 * tmp_size);
386 30 : var new_size = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeConstant ("2"), new CCodeIdentifier (temp_name + "_size"));
387 30 : ccode.add_assignment (new CCodeIdentifier (temp_name + "_size"), new_size);
388 :
389 30 : var renew_call = new CCodeFunctionCall (new CCodeIdentifier ("g_renew"));
390 30 : renew_call.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type)));
391 30 : renew_call.add_argument (new CCodeIdentifier (temp_name));
392 : // add one extra element for NULL-termination
393 30 : renew_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (temp_name + "_size"), new CCodeConstant ("1")));
394 30 : ccode.add_assignment (new CCodeIdentifier (temp_name), renew_call);
395 :
396 30 : ccode.close ();
397 :
398 30 : var element_access = new CCodeElementAccess (new CCodeIdentifier (temp_name), new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier (temp_name + "_length")));
399 30 : var element_expr = deserialize_expression (array_type.element_type, new CCodeIdentifier (element_name), null);
400 30 : ccode.add_assignment (element_access, element_expr);
401 : }
402 :
403 37 : var unref = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
404 37 : unref.add_argument (new CCodeIdentifier (element_name));
405 37 : ccode.add_expression (unref);
406 :
407 37 : ccode.close ();
408 :
409 37 : if (expr != null) {
410 37 : ccode.add_assignment (get_array_length (expr, dim), new CCodeIdentifier ("%s_length%d".printf (temp_name, dim)));
411 : }
412 : }
413 :
414 2 : CCodeExpression deserialize_buffer_array (ArrayType array_type, CCodeExpression variant_expr, CCodeExpression? expr) {
415 2 : string temp_name = "_tmp%d_".printf (next_temp_var_id++);
416 :
417 2 : var get_data_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get_data"));
418 2 : get_data_call.add_argument (variant_expr);
419 :
420 2 : var get_size_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get_size"));
421 2 : get_size_call.add_argument (variant_expr);
422 2 : ccode.add_declaration ("gsize", new CCodeVariableDeclarator (temp_name + "_length", get_size_call));
423 2 : var length = new CCodeIdentifier (temp_name + "_length");
424 :
425 : CCodeFunctionCall dup_call;
426 2 : if (context.require_glib_version (2, 68)) {
427 1 : dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup2"));
428 : } else {
429 1 : requires_memdup2 = true;
430 1 : dup_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_memdup2"));
431 : }
432 2 : dup_call.add_argument (get_data_call);
433 2 : dup_call.add_argument (length);
434 :
435 2 : ccode.add_declaration (get_ccode_name (array_type), new CCodeVariableDeclarator (temp_name, dup_call));
436 2 : if (expr != null) {
437 2 : ccode.add_assignment (get_array_length (expr, 1), length);
438 : }
439 :
440 2 : return new CCodeIdentifier (temp_name);
441 : }
442 :
443 12 : CCodeExpression? deserialize_struct (Struct st, CCodeExpression variant_expr) {
444 12 : string temp_name = "_tmp%d_".printf (next_temp_var_id++);
445 12 : string subiter_name = "_tmp%d_".printf (next_temp_var_id++);
446 :
447 12 : ccode.add_declaration (get_ccode_name (st), new CCodeVariableDeclarator (temp_name));
448 12 : ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator (subiter_name));
449 :
450 12 : var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
451 12 : iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name)));
452 12 : iter_call.add_argument (variant_expr);
453 12 : ccode.add_expression (iter_call);
454 :
455 12 : bool field_found = false;;
456 :
457 64 : foreach (Field f in st.get_fields ()) {
458 26 : if (f.binding != MemberBinding.INSTANCE) {
459 0 : continue;
460 : }
461 :
462 26 : field_found = true;
463 :
464 26 : read_expression (f.variable_type, new CCodeIdentifier (subiter_name), new CCodeMemberAccess (new CCodeIdentifier (temp_name), get_ccode_name (f)), f);
465 : }
466 :
467 12 : if (!field_found) {
468 0 : return null;
469 : }
470 :
471 12 : return new CCodeIdentifier (temp_name);
472 : }
473 :
474 7 : CCodeExpression? deserialize_hash_table (ObjectType type, CCodeExpression variant_expr) {
475 7 : string temp_name = "_tmp%d_".printf (next_temp_var_id++);
476 7 : string subiter_name = "_tmp%d_".printf (next_temp_var_id++);
477 7 : string key_name = "_tmp%d_".printf (next_temp_var_id++);
478 7 : string value_name = "_tmp%d_".printf (next_temp_var_id++);
479 :
480 16 : var type_args = type.get_type_arguments ();
481 7 : if (type_args.size != 2) {
482 1 : Report.error (type.source_reference, "Missing type-arguments for GVariant deserialization of `%s'", type.type_symbol.get_full_name ());
483 1 : return new CCodeInvalidExpression ();
484 : }
485 6 : var key_type = type_args.get (0);
486 6 : var value_type = type_args.get (1);
487 :
488 6 : ccode.add_declaration ("GHashTable*", new CCodeVariableDeclarator (temp_name));
489 6 : ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator (subiter_name));
490 6 : ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator (key_name));
491 6 : ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator (value_name));
492 :
493 6 : var hash_table_new = new CCodeFunctionCall (new CCodeIdentifier ("g_hash_table_new_full"));
494 6 : if (key_type.type_symbol.is_subtype_of (string_type.type_symbol)) {
495 5 : hash_table_new.add_argument (new CCodeIdentifier ("g_str_hash"));
496 5 : hash_table_new.add_argument (new CCodeIdentifier ("g_str_equal"));
497 1 : } else if (key_type.type_symbol == gvariant_type) {
498 0 : hash_table_new.add_argument (new CCodeIdentifier ("g_variant_hash"));
499 0 : hash_table_new.add_argument (new CCodeIdentifier ("g_variant_equal"));
500 : } else {
501 1 : hash_table_new.add_argument (new CCodeIdentifier ("g_direct_hash"));
502 1 : hash_table_new.add_argument (new CCodeIdentifier ("g_direct_equal"));
503 : }
504 :
505 6 : if (key_type.type_symbol.is_subtype_of (string_type.type_symbol)) {
506 5 : hash_table_new.add_argument (new CCodeIdentifier ("g_free"));
507 1 : } else if (key_type.type_symbol == gvariant_type) {
508 0 : hash_table_new.add_argument (new CCodeCastExpression (new CCodeIdentifier ("g_variant_unref"), "GDestroyNotify"));
509 1 : } else if (key_type.type_symbol.get_full_name () == "GLib.HashTable") {
510 0 : hash_table_new.add_argument (new CCodeCastExpression (new CCodeIdentifier ("g_hash_table_unref"), "GDestroyNotify"));
511 : } else {
512 1 : hash_table_new.add_argument (new CCodeConstant ("NULL"));
513 : }
514 :
515 6 : if (value_type.type_symbol.is_subtype_of (string_type.type_symbol)) {
516 2 : hash_table_new.add_argument (new CCodeIdentifier ("g_free"));
517 4 : } else if (value_type.type_symbol == gvariant_type) {
518 3 : hash_table_new.add_argument (new CCodeCastExpression (new CCodeIdentifier ("g_variant_unref"), "GDestroyNotify"));
519 1 : } else if (value_type.type_symbol.get_full_name () == "GLib.HashTable") {
520 1 : hash_table_new.add_argument (new CCodeCastExpression (new CCodeIdentifier ("g_hash_table_unref"), "GDestroyNotify"));
521 : } else {
522 0 : hash_table_new.add_argument (new CCodeConstant ("NULL"));
523 : }
524 6 : ccode.add_assignment (new CCodeIdentifier (temp_name), hash_table_new);
525 :
526 6 : var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
527 6 : iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name)));
528 6 : iter_call.add_argument (variant_expr);
529 6 : ccode.add_expression (iter_call);
530 :
531 6 : iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_loop"));
532 6 : iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name)));
533 6 : iter_call.add_argument (new CCodeConstant ("\"{?*}\""));
534 6 : iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (key_name)));
535 6 : iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (value_name)));
536 :
537 6 : ccode.open_while (iter_call);
538 :
539 6 : var key_expr = deserialize_expression (key_type, new CCodeIdentifier (key_name), null);
540 6 : var value_expr = deserialize_expression (value_type, new CCodeIdentifier (value_name), null);
541 6 : if (key_expr == null || value_expr == null) {
542 0 : return null;
543 : }
544 :
545 6 : var hash_table_insert = new CCodeFunctionCall (new CCodeIdentifier ("g_hash_table_insert"));
546 6 : hash_table_insert.add_argument (new CCodeIdentifier (temp_name));
547 6 : hash_table_insert.add_argument (convert_to_generic_pointer (key_expr, key_type));
548 6 : hash_table_insert.add_argument (convert_to_generic_pointer (value_expr, value_type));
549 6 : ccode.add_expression (hash_table_insert);
550 :
551 6 : ccode.close ();
552 :
553 6 : return new CCodeIdentifier (temp_name);
554 : }
555 :
556 241 : public override CCodeExpression? deserialize_expression (DataType type, CCodeExpression variant_expr, CCodeExpression? expr, CCodeExpression? error_expr = null, out bool may_fail = null) {
557 : BasicTypeInfo basic_type;
558 241 : CCodeExpression result = null;
559 241 : may_fail = false;
560 241 : if (is_string_marshalled_enum (type.type_symbol)) {
561 6 : get_basic_type_info ("s", out basic_type);
562 6 : result = deserialize_basic (basic_type, variant_expr, true);
563 12 : result = generate_enum_value_from_string (type as EnumValueType, result, error_expr);
564 6 : may_fail = true;
565 235 : } else if (get_basic_type_info (type.get_type_signature (), out basic_type)) {
566 179 : result = deserialize_basic (basic_type, variant_expr);
567 56 : } else if (type is ArrayType) {
568 32 : result = deserialize_array ((ArrayType) type, variant_expr, expr);
569 24 : } else if (type.type_symbol is Struct) {
570 12 : unowned Struct st = (Struct) type.type_symbol;
571 12 : result = deserialize_struct (st, variant_expr);
572 14 : if (result != null && type.nullable) {
573 2 : var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
574 2 : csizeof.add_argument (new CCodeIdentifier (get_ccode_name (st)));
575 : CCodeFunctionCall cdup;
576 2 : if (context.require_glib_version (2, 68)) {
577 1 : cdup = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup2"));
578 : } else {
579 1 : requires_memdup2 = true;
580 1 : cdup = new CCodeFunctionCall (new CCodeIdentifier ("_vala_memdup2"));
581 : }
582 2 : cdup.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, result));
583 2 : cdup.add_argument (csizeof);
584 4 : result = cdup;
585 : }
586 12 : } else if (type is ObjectType) {
587 12 : if (type.type_symbol.get_full_name () == "GLib.Variant") {
588 5 : var variant_get = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get_variant"));
589 5 : variant_get.add_argument (variant_expr);
590 240 : result = variant_get;
591 7 : } else if (type.type_symbol.get_full_name () == "GLib.HashTable") {
592 7 : result = deserialize_hash_table ((ObjectType) type, variant_expr);
593 : }
594 : }
595 :
596 241 : if (result == null) {
597 0 : Report.error (type.source_reference, "GVariant deserialization of type `%s' is not supported", type.to_string ());
598 0 : return new CCodeInvalidExpression ();
599 : }
600 :
601 241 : return result;
602 : }
603 :
604 246 : public void read_expression (DataType type, CCodeExpression iter_expr, CCodeExpression target_expr, Symbol? sym, CCodeExpression? error_expr = null, out bool may_fail = null) {
605 123 : var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_next_value"));
606 123 : iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, iter_expr));
607 :
608 123 : if (sym != null && get_dbus_signature (sym) != null) {
609 : // raw GVariant
610 6 : ccode.add_assignment (target_expr, iter_call);
611 6 : may_fail = false;
612 6 : return;
613 : }
614 :
615 117 : string temp_name = "_tmp%d_".printf (next_temp_var_id++);
616 :
617 117 : ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator (temp_name));
618 :
619 117 : var variant_expr = new CCodeIdentifier (temp_name);
620 :
621 117 : ccode.add_assignment (variant_expr, iter_call);
622 :
623 117 : var result = deserialize_expression (type, variant_expr, target_expr, error_expr, out may_fail);
624 117 : if (result == null) {
625 : // error already reported
626 0 : return;
627 : }
628 :
629 117 : ccode.add_assignment (target_expr, result);
630 :
631 117 : var unref = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
632 117 : unref.add_argument (variant_expr);
633 117 : ccode.add_expression (unref);
634 : }
635 :
636 6 : CCodeExpression? generate_enum_value_to_string (EnumValueType type, CCodeExpression? expr) {
637 6 : var en = type.type_symbol as Enum;
638 6 : var to_string_name = "%s_to_string".printf (get_ccode_lower_case_name (en, null));
639 :
640 6 : var to_string_call = new CCodeFunctionCall (new CCodeIdentifier (to_string_name));
641 6 : to_string_call.add_argument (expr);
642 :
643 6 : return to_string_call;
644 : }
645 :
646 3 : public CCodeFunction generate_enum_to_string_function_declaration (Enum en) {
647 3 : var to_string_name = "%s_to_string".printf (get_ccode_lower_case_name (en, null));
648 :
649 3 : var to_string_func = new CCodeFunction (to_string_name, "const char*");
650 3 : to_string_func.add_parameter (new CCodeParameter ("value", get_ccode_name (en)));
651 3 : to_string_func.modifiers |= CCodeModifiers.EXTERN;
652 3 : requires_vala_extern = true;
653 :
654 3 : return to_string_func;
655 : }
656 :
657 1 : public CCodeFunction generate_enum_to_string_function (Enum en) {
658 1 : var to_string_name = "%s_to_string".printf (get_ccode_lower_case_name (en, null));
659 :
660 1 : var to_string_func = new CCodeFunction (to_string_name, "const char*");
661 1 : to_string_func.add_parameter (new CCodeParameter ("value", get_ccode_name (en)));
662 :
663 1 : push_function (to_string_func);
664 :
665 1 : ccode.add_declaration ("const char *", new CCodeVariableDeclarator ("str"));
666 :
667 1 : ccode.open_switch (new CCodeIdentifier ("value"));
668 3 : foreach (EnumValue enum_value in en.get_values ()) {
669 1 : string dbus_value = get_dbus_value (enum_value, enum_value.name);
670 1 : ccode.add_case (new CCodeIdentifier (get_ccode_name (enum_value)));
671 1 : ccode.add_assignment (new CCodeIdentifier ("str"), new CCodeConstant ("\"%s\"".printf (dbus_value)));
672 1 : ccode.add_break ();
673 : }
674 :
675 1 : ccode.close();
676 :
677 1 : ccode.add_return (new CCodeIdentifier ("str"));
678 :
679 1 : pop_function ();
680 1 : return to_string_func;
681 : }
682 :
683 194 : CCodeExpression? serialize_basic (BasicTypeInfo basic_type, CCodeExpression expr) {
684 194 : var new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_new_" + basic_type.type_name));
685 194 : new_call.add_argument (expr);
686 194 : return new_call;
687 : }
688 :
689 38 : CCodeExpression? serialize_array (ArrayType array_type, CCodeExpression array_expr) {
690 38 : if (array_type.rank == 1 && array_type.get_type_signature () == "ay") {
691 2 : return serialize_buffer_array (array_type, array_expr);
692 : }
693 :
694 36 : string array_iter_name = "_tmp%d_".printf (next_temp_var_id++);
695 :
696 36 : ccode.add_declaration (get_ccode_name (array_type), new CCodeVariableDeclarator (array_iter_name));
697 36 : ccode.add_assignment (new CCodeIdentifier (array_iter_name), array_expr);
698 :
699 36 : return serialize_array_dim (array_type, 1, array_expr, new CCodeIdentifier (array_iter_name));
700 : }
701 :
702 46 : CCodeExpression? serialize_array_dim (ArrayType array_type, int dim, CCodeExpression array_expr, CCodeExpression array_iter_expr) {
703 46 : string builder_name = "_tmp%d_".printf (next_temp_var_id++);
704 46 : string index_name = "_tmp%d_".printf (next_temp_var_id++);
705 :
706 46 : ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator (builder_name));
707 46 : ccode.add_declaration (get_ccode_array_length_type (array_type), new CCodeVariableDeclarator (index_name));
708 :
709 46 : var gvariant_type = new CCodeFunctionCall (new CCodeIdentifier ("G_VARIANT_TYPE"));
710 46 : ArrayType array_type_copy = (ArrayType) array_type.copy ();
711 46 : array_type_copy.rank -= dim - 1;
712 46 : gvariant_type.add_argument (new CCodeConstant ("\"%s\"".printf (array_type_copy.get_type_signature ())));
713 :
714 46 : var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
715 46 : builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (builder_name)));
716 46 : builder_init.add_argument (gvariant_type);
717 46 : ccode.add_expression (builder_init);
718 :
719 46 : var cforinit = new CCodeAssignment (new CCodeIdentifier (index_name), new CCodeConstant ("0"));
720 46 : var cforcond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier (index_name), get_array_length (array_expr, dim));
721 46 : var cforiter = new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier (index_name));
722 46 : ccode.open_for (cforinit, cforcond, cforiter);
723 :
724 : CCodeExpression element_variant;
725 82 : if (dim < array_type.rank) {
726 10 : element_variant = serialize_array_dim (array_type, dim + 1, array_expr, array_iter_expr);
727 : } else {
728 36 : var element_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, array_iter_expr);
729 36 : element_variant = serialize_expression (array_type.element_type, element_expr);
730 : }
731 :
732 46 : var builder_add = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_add_value"));
733 46 : builder_add.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (builder_name)));
734 46 : builder_add.add_argument (element_variant);
735 46 : ccode.add_expression (builder_add);
736 :
737 82 : if (dim == array_type.rank) {
738 36 : var array_iter_incr = new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, array_iter_expr);
739 36 : ccode.add_expression (array_iter_incr);
740 : }
741 :
742 46 : ccode.close ();
743 :
744 46 : var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
745 46 : builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (builder_name)));
746 46 : return builder_end;
747 : }
748 :
749 2 : CCodeExpression serialize_buffer_array (ArrayType array_type, CCodeExpression array_expr) {
750 2 : string buffer_name = "_tmp%d_".printf (next_temp_var_id++);
751 :
752 2 : var gvariant_type = new CCodeFunctionCall (new CCodeIdentifier ("G_VARIANT_TYPE"));
753 2 : gvariant_type.add_argument (new CCodeConstant ("\"%s\"".printf (array_type.get_type_signature ())));
754 :
755 : CCodeFunctionCall dup_call;
756 2 : if (context.require_glib_version (2, 68)) {
757 1 : dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup2"));
758 : } else {
759 1 : requires_memdup2 = true;
760 1 : dup_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_memdup2"));
761 : }
762 2 : dup_call.add_argument (array_expr);
763 2 : dup_call.add_argument (get_array_length (array_expr, 1));
764 2 : ccode.add_declaration (get_ccode_name (array_type), new CCodeVariableDeclarator (buffer_name, dup_call));
765 :
766 2 : var new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_new_from_data"));
767 2 : new_call.add_argument (gvariant_type);
768 2 : new_call.add_argument (new CCodeIdentifier (buffer_name));
769 2 : new_call.add_argument (get_array_length (array_expr, 1));
770 2 : new_call.add_argument (new CCodeConstant ("TRUE"));
771 2 : new_call.add_argument (new CCodeIdentifier ("g_free"));
772 2 : new_call.add_argument (new CCodeIdentifier (buffer_name));
773 :
774 2 : return new_call;
775 : }
776 :
777 13 : CCodeExpression? serialize_struct (Struct st, CCodeExpression struct_expr) {
778 13 : string builder_name = "_tmp%d_".printf (next_temp_var_id++);
779 :
780 13 : ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator (builder_name));
781 :
782 13 : var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
783 13 : iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (builder_name)));
784 13 : iter_call.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
785 13 : ccode.add_expression (iter_call);
786 :
787 13 : bool field_found = false;;
788 :
789 65 : foreach (Field f in st.get_fields ()) {
790 26 : if (f.binding != MemberBinding.INSTANCE) {
791 0 : continue;
792 : }
793 :
794 26 : field_found = true;
795 :
796 26 : write_expression (f.variable_type, new CCodeIdentifier (builder_name), new CCodeMemberAccess (struct_expr, get_ccode_name (f)), f);
797 : }
798 :
799 13 : if (!field_found) {
800 0 : return null;
801 : }
802 :
803 13 : var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
804 13 : builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (builder_name)));
805 13 : return builder_end;
806 : }
807 :
808 9 : CCodeExpression? serialize_hash_table (ObjectType type, CCodeExpression hash_table_expr) {
809 9 : string subiter_name = "_tmp%d_".printf (next_temp_var_id++);
810 9 : string tableiter_name = "_tmp%d_".printf (next_temp_var_id++);
811 9 : string key_name = "_tmp%d_".printf (next_temp_var_id++);
812 9 : string value_name = "_tmp%d_".printf (next_temp_var_id++);
813 :
814 9 : var type_args = type.get_type_arguments ();
815 9 : if (type_args.size != 2) {
816 1 : Report.error (type.source_reference, "Missing type-arguments for GVariant serialization of `%s'", type.type_symbol.get_full_name ());
817 1 : return new CCodeInvalidExpression ();
818 : }
819 8 : var key_type = type_args.get (0);
820 8 : var value_type = type_args.get (1);
821 :
822 8 : ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator (subiter_name));
823 8 : ccode.add_declaration ("GHashTableIter", new CCodeVariableDeclarator (tableiter_name));
824 8 : ccode.add_declaration ("gpointer", new CCodeVariableDeclarator (key_name));
825 8 : ccode.add_declaration ("gpointer", new CCodeVariableDeclarator (value_name));
826 :
827 8 : var iter_init_call = new CCodeFunctionCall (new CCodeIdentifier ("g_hash_table_iter_init"));
828 8 : iter_init_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (tableiter_name)));
829 8 : iter_init_call.add_argument (hash_table_expr);
830 8 : ccode.add_expression (iter_init_call);
831 :
832 8 : var gvariant_type = new CCodeFunctionCall (new CCodeIdentifier ("G_VARIANT_TYPE"));
833 8 : gvariant_type.add_argument (new CCodeConstant ("\"%s\"".printf (type.get_type_signature ())));
834 :
835 8 : var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
836 8 : iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name)));
837 8 : iter_call.add_argument (gvariant_type);
838 8 : ccode.add_expression (iter_call);
839 :
840 8 : var iter_next_call = new CCodeFunctionCall (new CCodeIdentifier ("g_hash_table_iter_next"));
841 8 : iter_next_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (tableiter_name)));
842 8 : iter_next_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (key_name)));
843 8 : iter_next_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (value_name)));
844 :
845 8 : ccode.open_while (iter_next_call);
846 :
847 8 : ccode.add_declaration (get_ccode_name (key_type), new CCodeVariableDeclarator ("_key"));
848 8 : ccode.add_declaration (get_ccode_name (value_type), new CCodeVariableDeclarator ("_value"));
849 :
850 8 : ccode.add_assignment (new CCodeIdentifier ("_key"), convert_from_generic_pointer (new CCodeIdentifier (key_name), key_type));
851 8 : ccode.add_assignment (new CCodeIdentifier ("_value"), convert_from_generic_pointer (new CCodeIdentifier (value_name), value_type));
852 :
853 8 : var serialized_key = serialize_expression (key_type, new CCodeIdentifier ("_key"));
854 8 : var serialized_value = serialize_expression (value_type, new CCodeIdentifier ("_value"));
855 8 : if (serialized_key == null || serialized_value == null) {
856 0 : return null;
857 : }
858 :
859 8 : iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_add"));
860 8 : iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name)));
861 8 : iter_call.add_argument (new CCodeConstant ("\"{?*}\""));
862 8 : iter_call.add_argument (serialized_key);
863 8 : iter_call.add_argument (serialized_value);
864 8 : ccode.add_expression (iter_call);
865 :
866 8 : ccode.close ();
867 :
868 8 : iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
869 8 : iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name)));
870 8 : return iter_call;
871 : }
872 :
873 262 : public override CCodeExpression? serialize_expression (DataType type, CCodeExpression expr) {
874 : BasicTypeInfo basic_type;
875 262 : CCodeExpression result = null;
876 262 : if (is_string_marshalled_enum (type.type_symbol)) {
877 6 : get_basic_type_info ("s", out basic_type);
878 12 : result = generate_enum_value_to_string (type as EnumValueType, expr);
879 6 : result = serialize_basic (basic_type, result);
880 256 : } else if (get_basic_type_info (type.get_type_signature (), out basic_type)) {
881 188 : result = serialize_basic (basic_type, expr);
882 68 : } else if (type is ArrayType) {
883 38 : result = serialize_array ((ArrayType) type, expr);
884 43 : } else if (type.type_symbol is Struct) {
885 13 : var st_expr = expr;
886 13 : if (type.nullable) {
887 1 : st_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, st_expr);
888 : }
889 13 : result = serialize_struct ((Struct) type.type_symbol, st_expr);
890 17 : } else if (type is ObjectType) {
891 16 : if (type.type_symbol.get_full_name () == "GLib.Variant") {
892 7 : var variant_new = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_new_variant"));
893 7 : variant_new.add_argument (expr);
894 262 : result = variant_new;
895 9 : } else if (type.type_symbol.get_full_name () == "GLib.HashTable") {
896 9 : result = serialize_hash_table ((ObjectType) type, expr);
897 : }
898 : }
899 :
900 262 : if (result == null) {
901 1 : Report.error (type.source_reference, "GVariant serialization of type `%s' is not supported", type.to_string ());
902 1 : return new CCodeInvalidExpression ();
903 : }
904 :
905 262 : return result;
906 : }
907 :
908 346 : public void write_expression (DataType type, CCodeExpression builder_expr, CCodeExpression expr, Symbol? sym) {
909 173 : var variant_expr = expr;
910 173 : if (sym == null || get_dbus_signature (sym) == null) {
911 : // perform boxing
912 166 : variant_expr = serialize_expression (type, expr);
913 : }
914 346 : if (variant_expr != null) {
915 173 : var builder_add = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_add_value"));
916 173 : builder_add.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, builder_expr));
917 173 : builder_add.add_argument (variant_expr);
918 173 : ccode.add_expression (builder_add);
919 : }
920 : }
921 : }
|