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