Line data Source code
1 : /* valagvaluemodule.vala
2 : *
3 : * Copyright (C) 2019 Rico Tzschichholz
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 : * Rico Tzschichholz <ricotz@ubuntu.com>
21 : */
22 :
23 2914 : public class Vala.GValueModule : GAsyncModule {
24 1800 : public override void visit_cast_expression (CastExpression expr) {
25 1746 : unowned DataType? value_type = expr.inner.value_type;
26 1746 : unowned DataType? target_type = expr.type_reference;
27 :
28 1746 : if (expr.is_non_null_cast || value_type == null || gvalue_type == null
29 1635 : || value_type.type_symbol != gvalue_type || target_type.type_symbol == gvalue_type
30 55 : || get_ccode_type_id (target_type) == "") {
31 1692 : base.visit_cast_expression (expr);
32 1692 : return;
33 : }
34 :
35 54 : generate_type_declaration (expr.type_reference, cfile);
36 :
37 : // explicit conversion from GValue
38 54 : var ccall = new CCodeFunctionCall (get_value_getter_function (target_type));
39 : CCodeExpression gvalue;
40 54 : if (value_type.nullable) {
41 86 : gvalue = get_cvalue (expr.inner);
42 : } else {
43 23 : gvalue = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue (expr.inner));
44 : }
45 54 : ccall.add_argument (gvalue);
46 :
47 63 : if (value_type.is_disposable ()) {
48 9 : var temp_var = get_temp_variable (value_type, true, expr, false);
49 9 : emit_temp_var (temp_var);
50 9 : var temp_ref = get_variable_cexpression (temp_var.name);
51 9 : ccode.add_assignment (temp_ref, get_cvalue (expr.inner));
52 :
53 : // value needs to be kept alive until the end of this block
54 9 : temp_ref_values.insert (0, get_local_cvalue (temp_var));
55 : }
56 :
57 : CCodeExpression rv;
58 56 : if (target_type is ArrayType) {
59 2 : var temp_var = get_temp_variable (target_type, true, expr, false);
60 2 : emit_temp_var (temp_var);
61 2 : var temp_ref = get_variable_cexpression (temp_var.name);
62 2 : ccode.add_assignment (temp_ref, ccall);
63 2 : rv = temp_ref;
64 :
65 : // null-terminated string array
66 2 : var len_call = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length"));
67 2 : len_call.add_argument (rv);
68 2 : append_array_length (expr, len_call);
69 53 : } else if (target_type is StructValueType) {
70 1 : var temp_var = get_temp_variable (new PointerType (target_type), true, expr, false);
71 1 : emit_temp_var (temp_var);
72 1 : var temp_ref = get_variable_cexpression (temp_var.name);
73 1 : ccode.add_assignment (temp_ref, ccall);
74 1 : rv = temp_ref;
75 :
76 : // default value to fallback to
77 1 : var temp_value = create_temp_value (target_type, true, expr, true);
78 1 : var ctemp = get_cvalue_ (temp_value);
79 :
80 1 : var holds = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_HOLDS"));
81 1 : holds.add_argument (gvalue);
82 1 : holds.add_argument (new CCodeIdentifier (get_ccode_type_id (target_type)));
83 1 : var cond = new CCodeBinaryExpression (CCodeBinaryOperator.AND, holds, rv);
84 1 : var warn = new CCodeFunctionCall (new CCodeIdentifier ("g_warning"));
85 1 : warn.add_argument (new CCodeConstant ("\"Invalid GValue unboxing (wrong type or NULL)\""));
86 1 : var fail = new CCodeCommaExpression ();
87 1 : fail.append_expression (warn);
88 1 : fail.append_expression (ctemp);
89 1 : rv = new CCodeConditionalExpression (cond, new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, rv), fail);
90 : } else {
91 51 : rv = ccall;
92 : }
93 :
94 54 : set_cvalue (expr, rv);
95 : }
96 :
97 92 : public override CCodeExpression get_value_getter_function (DataType type_reference) {
98 105 : var array_type = type_reference as ArrayType;
99 92 : if (type_reference.type_symbol != null) {
100 86 : return new CCodeIdentifier (get_ccode_get_value_function (type_reference.type_symbol));
101 6 : } else if (array_type != null && array_type.element_type.type_symbol == string_type.type_symbol) {
102 : // G_TYPE_STRV
103 4 : return new CCodeIdentifier ("g_value_get_boxed");
104 : } else {
105 2 : return new CCodeIdentifier ("g_value_get_pointer");
106 : }
107 : }
108 :
109 419 : public override CCodeExpression get_value_setter_function (DataType type_reference) {
110 419 : var array_type = type_reference as ArrayType;
111 419 : if (type_reference.type_symbol != null) {
112 407 : return new CCodeIdentifier (get_ccode_set_value_function (type_reference.type_symbol));
113 12 : } else if (array_type != null && array_type.element_type.type_symbol == string_type.type_symbol) {
114 : // G_TYPE_STRV
115 8 : return new CCodeIdentifier ("g_value_set_boxed");
116 : } else {
117 4 : return new CCodeIdentifier ("g_value_set_pointer");
118 : }
119 : }
120 :
121 24 : public override CCodeExpression get_value_taker_function (DataType type_reference) {
122 24 : var array_type = type_reference as ArrayType;
123 24 : if (type_reference.type_symbol != null) {
124 21 : return new CCodeIdentifier (get_ccode_take_value_function (type_reference.type_symbol));
125 3 : } else if (array_type != null && array_type.element_type.type_symbol == string_type.type_symbol) {
126 : // G_TYPE_STRV
127 3 : return new CCodeIdentifier ("g_value_take_boxed");
128 : } else {
129 0 : return new CCodeIdentifier ("g_value_set_pointer");
130 : }
131 : }
132 : }
|