From: Jürg Billeter Date: Fri, 3 Oct 2008 13:17:10 +0000 (+0000) Subject: Generate code to support GValue and GParamSpec for fundamental classes, X-Git-Tag: VALA_0_4_0~43 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0ae7748b60d8cd686e0733b06d1b727f94b9d5a6;p=thirdparty%2Fvala.git Generate code to support GValue and GParamSpec for fundamental classes, 2008-10-03 Jürg Billeter * vala/valaclass.vala: * vala/valainterfacewriter.vala: * vala/valatypesymbol.vala: * gobject/valaccodeclassbinding.vala: * gobject/valaccodegenerator.vala: * gobject/valaccodegeneratorsourcefile.vala: * gobject/valaccodetypesymbolbinding.vala: * gobject/valaclassregisterfunction.vala: * gobject/valatyperegisterfunction.vala: * vapi/glib-2.0.vapi: Generate code to support GValue and GParamSpec for fundamental classes, patch by Florian Brosch, fixes bug 549480 svn path=/trunk/; revision=1818 --- diff --git a/ChangeLog b/ChangeLog index f594ae09f..35f422c3f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2008-10-03 Jürg Billeter + + * vala/valaclass.vala: + * vala/valainterfacewriter.vala: + * vala/valatypesymbol.vala: + * gobject/valaccodeclassbinding.vala: + * gobject/valaccodegenerator.vala: + * gobject/valaccodegeneratorsourcefile.vala: + * gobject/valaccodetypesymbolbinding.vala: + * gobject/valaclassregisterfunction.vala: + * gobject/valatyperegisterfunction.vala: + * vapi/glib-2.0.vapi: + + Generate code to support GValue and GParamSpec for fundamental + classes, patch by Florian Brosch, fixes bug 549480 + 2008-10-03 Jürg Billeter * vapi/glib-2.0.vapi: diff --git a/gobject/valaccodeclassbinding.vala b/gobject/valaccodeclassbinding.vala index 10461e80d..9d20fb00d 100644 --- a/gobject/valaccodeclassbinding.vala +++ b/gobject/valaccodeclassbinding.vala @@ -36,6 +36,7 @@ public class Vala.CCodeClassBinding : CCodeObjectTypeSymbolBinding { var old_type_symbol = codegen.current_type_symbol; var old_class = codegen.current_class; var old_instance_struct = codegen.instance_struct; + var old_param_spec_struct = codegen.param_spec_struct; var old_type_struct = codegen.type_struct; var old_instance_priv_struct = codegen.instance_priv_struct; var old_prop_enum = codegen.prop_enum; @@ -56,6 +57,7 @@ public class Vala.CCodeClassBinding : CCodeObjectTypeSymbolBinding { return; } + if (!cl.is_static) { codegen.instance_struct = new CCodeStruct ("_%s".printf (cl.get_cname ())); codegen.type_struct = new CCodeStruct ("_%sClass".printf (cl.get_cname ())); @@ -67,6 +69,8 @@ public class Vala.CCodeClassBinding : CCodeObjectTypeSymbolBinding { codegen.instance_finalize_fragment = new CCodeFragment (); } + + CCodeFragment decl_frag; CCodeFragment def_frag; if (cl.access != SymbolAccessibility.PRIVATE) { @@ -153,6 +157,25 @@ public class Vala.CCodeClassBinding : CCodeObjectTypeSymbolBinding { if (is_gtypeinstance) { if (is_fundamental) { + codegen.param_spec_struct = new CCodeStruct ( "_%sParamSpec%s".printf(cl.parent_symbol.get_cprefix (), cl.name)); + codegen.param_spec_struct.add_field ("GParamSpec", "parent_instance"); + def_frag.append (codegen.param_spec_struct); + + decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (codegen.param_spec_struct.name), new CCodeVariableDeclarator ( "%sParamSpec%s".printf(cl.parent_symbol.get_cprefix (), cl.name)))); + + + codegen.gvaluecollector_h_needed = true; + + add_type_value_table_init_function (cl); + add_type_value_table_free_function (cl); + add_type_value_table_copy_function (cl); + add_type_value_table_peek_pointer_function (cl); + add_type_value_table_collect_value_function (cl); + add_type_value_table_lcopy_value_function (cl); + add_g_param_spec_type_function (cl); + add_g_value_get_function (cl); + add_g_value_set_function (cl); + var ref_count = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"), new CCodeConstant ("1")); codegen.instance_init_fragment.append (new CCodeExpressionStatement (ref_count)); } else if (is_gobject) { @@ -291,12 +314,358 @@ public class Vala.CCodeClassBinding : CCodeObjectTypeSymbolBinding { codegen.instance_init_fragment = old_instance_init_fragment; codegen.instance_finalize_fragment = old_instance_finalize_fragment; } - + + private void add_type_value_table_init_function (Class cl) { + var function = new CCodeFunction ("%svalue_%s_init".printf (cl.parent_symbol.get_lower_case_cprefix (), cl.name.down() ), "void"); + function.add_parameter (new CCodeFormalParameter ("value", "GValue*")); + function.modifiers = CCodeModifiers.STATIC; + + var init_block = new CCodeBlock (); + function.block = init_block; + + init_block.add_statement(new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"),new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE))); + codegen.source_type_member_definition.append (function); + } + + private void add_type_value_table_free_function (Class cl) { + var function = new CCodeFunction ("%svalue_%s_free_value".printf (cl.parent_symbol.get_lower_case_cprefix (), cl.name.down()), "void"); + function.add_parameter (new CCodeFormalParameter ("value", "GValue*")); + function.modifiers = CCodeModifiers.STATIC; + + var init_block = new CCodeBlock (); + function.block = init_block; + + var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); + var ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_lower_case_cprefix () + "unref")); + ccall.add_argument ( vpointer ); + + var ifbody = new CCodeBlock (); + ifbody.add_statement ( new CCodeExpressionStatement(ccall) ); + + init_block.add_statement(new CCodeIfStatement (vpointer, ifbody)); + codegen.source_type_member_definition.append (function); + } + + private void add_type_value_table_copy_function (Class cl) { + var function = new CCodeFunction ("%svalue_%s_copy_value".printf (cl.parent_symbol.get_lower_case_cprefix (), cl.name.down()), "void"); + function.add_parameter (new CCodeFormalParameter ("src_value", "const GValue*")); + function.add_parameter (new CCodeFormalParameter ("dest_value", "GValue*")); + function.modifiers = CCodeModifiers.STATIC; + + var init_block = new CCodeBlock (); + function.block = init_block; + + var dest_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dest_value"), "data[0]"),"v_pointer"); + var src_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("src_value"), "data[0]"),"v_pointer"); + + var ref_ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_lower_case_cprefix () + "ref")); + ref_ccall.add_argument ( src_vpointer ); + + var true_stmt = new CCodeBlock (); + true_stmt.add_statement(new CCodeExpressionStatement(new CCodeAssignment (dest_vpointer, ref_ccall, CCodeAssignmentOperator.SIMPLE))); + + var false_stmt = new CCodeBlock (); + false_stmt.add_statement (new CCodeExpressionStatement( new CCodeAssignment (dest_vpointer, new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE))); + + var if_statement = new CCodeIfStatement (src_vpointer, true_stmt, false_stmt); + init_block.add_statement (if_statement); + + codegen.source_type_member_definition.append (function); + } + + private void add_type_value_table_peek_pointer_function (Class cl) { + var function = new CCodeFunction ("%svalue_%s_peek_pointer".printf (cl.parent_symbol.get_lower_case_cprefix (), cl.name.down()), "gpointer"); + function.add_parameter (new CCodeFormalParameter ("value", "const GValue*")); + function.modifiers = CCodeModifiers.STATIC; + + var init_block = new CCodeBlock (); + function.block = init_block; + + var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); + var ret = new CCodeReturnStatement ( vpointer ); + init_block.add_statement (ret); + + codegen.source_type_member_definition.append (function); + } + + private void add_type_value_table_lcopy_value_function ( Class cl ) { + var function = new CCodeFunction ("%svalue_%s_lcopy_value".printf (cl.parent_symbol.get_lower_case_cprefix (), cl.name.down()), "gchar*"); + function.add_parameter (new CCodeFormalParameter ("value", "const GValue*")); + function.add_parameter (new CCodeFormalParameter ("n_collect_values", "guint")); + function.add_parameter (new CCodeFormalParameter ("collect_values", "GTypeCValue*")); + function.add_parameter (new CCodeFormalParameter ("collect_flags", "guint")); + function.modifiers = CCodeModifiers.STATIC; + + var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); + var object_p_ptr = new CCodeIdentifier ("*object_p"); + var null_ = new CCodeConstant("NULL"); + + var init_block = new CCodeBlock (); + + var ctypedecl = new CCodeDeclaration (cl.get_cname()+"**"); + ctypedecl.add_declarator ( new CCodeVariableDeclarator.with_initializer("object_p", new CCodeMemberAccess(new CCodeIdentifier ("collect_values[0]"),"v_pointer"))); + init_block.add_statement (ctypedecl); + + var assert_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("object_p")); + function.block = init_block; + var assert_true = new CCodeBlock (); + var if_assert = new CCodeIfStatement (assert_condition, assert_true); + init_block.add_statement (if_assert); + + var main_else_true = new CCodeBlock (); + var main_else_if_true = new CCodeBlock (); + var main_else_if_condition = new CCodeBinaryExpression ( CCodeBinaryOperator.AND, new CCodeIdentifier ("collect_flags"), new CCodeIdentifier ("G_VALUE_NOCOPY_CONTENTS")); + var main_else_if = new CCodeIfStatement (main_else_if_condition, main_else_if_true, main_else_true); + + var main_true = new CCodeBlock (); + var main_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, vpointer); + var if_main = new CCodeIfStatement (main_condition, main_true, main_else_if); + init_block.add_statement (if_main); + + var ref_fct = new CCodeFunctionCall (new CCodeIdentifier (cl.get_ref_function())); + ref_fct.add_argument (vpointer); + + main_true.add_statement (new CCodeExpressionStatement( new CCodeAssignment (object_p_ptr, null_, CCodeAssignmentOperator.SIMPLE))); + main_else_if_true.add_statement (new CCodeExpressionStatement( new CCodeAssignment (object_p_ptr, vpointer, CCodeAssignmentOperator.SIMPLE))); + main_else_true.add_statement (new CCodeExpressionStatement( new CCodeAssignment (object_p_ptr, ref_fct, CCodeAssignmentOperator.SIMPLE))); + + init_block.add_statement ( new CCodeReturnStatement ( null_ )); + codegen.source_type_member_definition.append (function); + } + + private void add_type_value_table_collect_value_function (Class cl) { + var function = new CCodeFunction ("%svalue_%s_collect_value".printf (cl.parent_symbol.get_lower_case_cprefix (), cl.name.down()), "gchar*"); + function.add_parameter (new CCodeFormalParameter ("value", "GValue*")); + function.add_parameter (new CCodeFormalParameter ("n_collect_values", "guint")); + function.add_parameter (new CCodeFormalParameter ("collect_values", "GTypeCValue*")); + function.add_parameter (new CCodeFormalParameter ("collect_flags", "guint")); + function.modifiers = CCodeModifiers.STATIC; + + var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); + + var init_block = new CCodeBlock (); + function.block = init_block; + + var condition = new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"), "v_pointer"); + var true_stmt = new CCodeBlock (); + var false_stmt = new CCodeBlock (); + var if_statement = new CCodeIfStatement (condition, true_stmt, false_stmt); + init_block.add_statement (if_statement); + + var obj_identifier = new CCodeIdentifier ("object"); + + var ctypedecl = new CCodeDeclaration (cl.get_cname()+"*"); + ctypedecl.add_declarator ( new CCodeVariableDeclarator.with_initializer("object", vpointer ) ); + true_stmt.add_statement ( ctypedecl ); + + var l_expression = new CCodeMemberAccess(new CCodeMemberAccess.pointer (obj_identifier, "parent_instance"),"g_class"); + var sub_condition = new CCodeBinaryExpression ( CCodeBinaryOperator.EQUALITY, l_expression, new CCodeConstant("NULL")); + var sub_true_stmt = new CCodeBlock (); + var sub_false_stmt = new CCodeBlock (); + + var reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible")); + var type_check = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_TYPE")); + type_check.add_argument ( new CCodeIdentifier ("object") ); + reg_call.add_argument ( type_check ); + + var stored_type = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE")); + stored_type.add_argument ( new CCodeIdentifier ("value") ); + reg_call.add_argument ( stored_type ); + + var type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME")); + type_name_fct.add_argument (new CCodeConstant("value")); + + var true_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat")); + true_return.add_argument (new CCodeConstant("\"invalid unclassed object pointer for value type `\"")); + true_return.add_argument ( type_name_fct ); + true_return.add_argument (new CCodeConstant("\"'\"")); + true_return.add_argument (new CCodeConstant("NULL")); + sub_true_stmt.add_statement (new CCodeReturnStatement ( true_return )); + + var false_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat")); + false_return.add_argument (new CCodeConstant("\"invalid object type `\"")); + false_return.add_argument ( type_check ); + false_return.add_argument (new CCodeConstant("\"' for value type `\"")); + false_return.add_argument ( type_name_fct ); + false_return.add_argument (new CCodeConstant("\"'\"")); + false_return.add_argument (new CCodeConstant("NULL")); + sub_false_stmt.add_statement (new CCodeReturnStatement ( false_return )); + + var sub_else_if_statement = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, reg_call), sub_false_stmt ); + sub_else_if_statement.else_if = true; + var sub_if_statement = new CCodeIfStatement (sub_condition, sub_true_stmt, sub_else_if_statement ); + true_stmt.add_statement ( sub_if_statement ); + + var else_assigment = new CCodeExpressionStatement( new CCodeAssignment (vpointer, new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE)); + false_stmt.add_statement ( else_assigment ); + + init_block.add_statement ( new CCodeReturnStatement ( new CCodeConstant("NULL") )); + codegen.source_type_member_definition.append (function); + } + + private void add_g_param_spec_type_function (Class cl) { + var function_name = "%sparam_spec_%s".printf (cl.parent_symbol.get_lower_case_cprefix (), cl.name.down()); + + var function = new CCodeFunction (function_name, "GParamSpec*"); + function.add_parameter (new CCodeFormalParameter ("name", "const gchar*")); + function.add_parameter (new CCodeFormalParameter ("nick", "const gchar*")); + function.add_parameter (new CCodeFormalParameter ("blurb", "const gchar*")); + function.add_parameter (new CCodeFormalParameter ("object_type", "GType")); + function.add_parameter (new CCodeFormalParameter ("flags", "GParamFlags")); + + cl.set_param_spec_function ( function_name ); + + if (cl.access == SymbolAccessibility.PRIVATE) { + function.modifiers = CCodeModifiers.STATIC; + codegen.source_type_member_declaration.append (function.copy ()); + } else { + codegen.header_type_member_declaration.append (function.copy ()); + } + + var init_block = new CCodeBlock (); + function.block = init_block; + + var ctypedecl = new CCodeDeclaration ("%sParamSpec%s*".printf (cl.parent_symbol.get_cprefix (), cl.name)); + ctypedecl.add_declarator ( new CCodeVariableDeclarator ("spec")); + init_block.add_statement (ctypedecl); + + var subccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_is_a")); + subccall.add_argument (new CCodeIdentifier ("object_type")); + subccall.add_argument (new CCodeIdentifier ( cl.get_type_id() )); + + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail")); + ccall.add_argument (subccall); + ccall.add_argument (new CCodeIdentifier ("NULL")); + init_block.add_statement (new CCodeExpressionStatement (ccall)); + + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_internal")); + ccall.add_argument (new CCodeIdentifier ( "G_TYPE_PARAM_OBJECT" )); + ccall.add_argument (new CCodeIdentifier ("name")); + ccall.add_argument (new CCodeIdentifier ("nick")); + ccall.add_argument (new CCodeIdentifier ("blurb")); + ccall.add_argument (new CCodeIdentifier ("flags")); + + init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("spec"), ccall, CCodeAssignmentOperator.SIMPLE ))); + + ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_PARAM_SPEC")); + ccall.add_argument (new CCodeIdentifier ("spec")); + + init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "value_type"), new CCodeIdentifier ("object_type"), CCodeAssignmentOperator.SIMPLE ))); + init_block.add_statement (new CCodeReturnStatement (ccall)); + codegen.source_type_member_definition.append (function); + } + + private void add_g_value_set_function (Class cl) { + var function = new CCodeFunction (cl.get_set_value_function (), "void"); + function.add_parameter (new CCodeFormalParameter ("value", "GValue*")); + function.add_parameter (new CCodeFormalParameter ("v_object", "gpointer")); + + if (cl.access == SymbolAccessibility.PRIVATE) { + function.modifiers = CCodeModifiers.STATIC; + codegen.source_type_member_declaration.append (function.copy ()); + } else { + codegen.header_type_member_declaration.append (function.copy ()); + } + + var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); + + var init_block = new CCodeBlock (); + function.block = init_block; + + var ctypedecl = new CCodeDeclaration (cl.get_cname()+"*"); + ctypedecl.add_declarator ( new CCodeVariableDeclarator ("old")); + init_block.add_statement (ctypedecl); + + var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE")); + ccall_typecheck.add_argument (new CCodeIdentifier ( "value" )); + ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() )); + + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); + ccall.add_argument (ccall_typecheck); + init_block.add_statement (new CCodeExpressionStatement (ccall)); + + init_block.add_statement(new CCodeExpressionStatement (new CCodeAssignment (new CCodeConstant ("old"), vpointer, CCodeAssignmentOperator.SIMPLE))); + + var true_stmt = new CCodeBlock (); + var false_stmt = new CCodeBlock (); + var if_statement = new CCodeIfStatement (new CCodeIdentifier ("v_object"), true_stmt, false_stmt); + init_block.add_statement (if_statement); + + + ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE")); + ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" )); + ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() )); + + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); + ccall.add_argument (ccall_typecheck); + true_stmt.add_statement (new CCodeExpressionStatement (ccall)); + + var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE")); + ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" )); + + var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE")); + ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" )); + + var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible")); + ccall_typecompatible.add_argument (ccall_typefrominstance); + ccall_typecompatible.add_argument (ccall_gvaluetype); + + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); + ccall.add_argument (ccall_typecompatible); + true_stmt.add_statement (new CCodeExpressionStatement (ccall)); + + true_stmt.add_statement(new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("v_object"), CCodeAssignmentOperator.SIMPLE))); + + ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_ref_function ())); + ccall.add_argument (vpointer); + true_stmt.add_statement (new CCodeExpressionStatement (ccall)); + + false_stmt.add_statement(new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE))); + + true_stmt = new CCodeBlock (); + if_statement = new CCodeIfStatement (new CCodeIdentifier ("old"), true_stmt); + init_block.add_statement (if_statement); + + ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_unref_function ())); + ccall.add_argument (new CCodeIdentifier ("old")); + true_stmt.add_statement (new CCodeExpressionStatement (ccall)); + codegen.source_type_member_definition.append (function); + } + + private void add_g_value_get_function (Class cl) { + var function = new CCodeFunction (cl.get_get_value_function (), "gpointer"); + function.add_parameter (new CCodeFormalParameter ("value", "const GValue*")); + + if (cl.access == SymbolAccessibility.PRIVATE) { + function.modifiers = CCodeModifiers.STATIC; + codegen.source_type_member_declaration.append (function.copy ()); + } else { + codegen.header_type_member_declaration.append (function.copy ()); + } + + var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); + + var init_block = new CCodeBlock (); + function.block = init_block; + + var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE")); + ccall_typecheck.add_argument (new CCodeIdentifier ( "value" )); + ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() )); + + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail")); + ccall.add_argument (ccall_typecheck); + ccall.add_argument (new CCodeIdentifier ( "NULL" )); + init_block.add_statement (new CCodeExpressionStatement (ccall)); + + init_block.add_statement (new CCodeReturnStatement ( vpointer )); + codegen.source_type_member_definition.append (function); + } + private void add_class_init_function (Class cl) { var class_init = new CCodeFunction ("%s_class_init".printf (cl.get_lower_case_cname (null)), "void"); class_init.add_parameter (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ()))); class_init.modifiers = CCodeModifiers.STATIC; - + var init_block = new CCodeBlock (); class_init.block = init_block; diff --git a/gobject/valaccodegenerator.vala b/gobject/valaccodegenerator.vala index 5064ecfae..7066d3b09 100644 --- a/gobject/valaccodegenerator.vala +++ b/gobject/valaccodegenerator.vala @@ -58,6 +58,7 @@ public class Vala.CCodeGenerator : CodeGenerator { public CCodeFragment source_signal_marshaller_definition; public CCodeFragment module_init_fragment; + public CCodeStruct param_spec_struct; public CCodeStruct instance_struct; public CCodeStruct type_struct; public CCodeStruct instance_priv_struct; @@ -127,6 +128,7 @@ public class Vala.CCodeGenerator : CodeGenerator { public string module_init_param_name; public bool string_h_needed; + public bool gvaluecollector_h_needed; private bool requires_free_checked; private bool requires_array_free; public bool requires_array_move; diff --git a/gobject/valaccodegeneratorsourcefile.vala b/gobject/valaccodegeneratorsourcefile.vala index 4149d00eb..e9c38f825 100644 --- a/gobject/valaccodegeneratorsourcefile.vala +++ b/gobject/valaccodegeneratorsourcefile.vala @@ -193,6 +193,7 @@ public class Vala.CCodeGenerator { next_temp_var_id = 0; string_h_needed = false; + gvaluecollector_h_needed = false; dbus_glib_h_needed = false; requires_free_checked = false; requires_array_free = false; @@ -292,6 +293,10 @@ public class Vala.CCodeGenerator { source_include_directives.append (new CCodeIncludeDirective ("string.h")); } + if (gvaluecollector_h_needed) { + source_include_directives.append (new CCodeIncludeDirective ("gobject/gvaluecollector.h")); + } + if (dbus_glib_h_needed) { source_include_directives.append (new CCodeIncludeDirective ("dbus/dbus-glib.h")); } diff --git a/gobject/valaccodetypesymbolbinding.vala b/gobject/valaccodetypesymbolbinding.vala index 939b10914..1b991e3fb 100644 --- a/gobject/valaccodetypesymbolbinding.vala +++ b/gobject/valaccodetypesymbolbinding.vala @@ -29,9 +29,17 @@ public abstract class Vala.CCodeTypeSymbolBinding : CCodeBinding { cspec.add_argument (prop.get_canonical_cconstant ()); cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.nick))); cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.blurb))); - if ((prop.property_type.data_type is Class && ((Class) prop.property_type.data_type).is_subtype_of (codegen.gobject_type)) || prop.property_type.data_type is Interface) { - cspec.call = new CCodeIdentifier ("g_param_spec_object"); - cspec.add_argument (new CCodeIdentifier (prop.property_type.data_type.get_type_id ())); + + + if ((prop.property_type.data_type is Class && !(((Class) prop.property_type.data_type).is_compact)) || prop.property_type.data_type is Interface) { + //if ((prop.property_type.data_type is Class && ((Class) prop.property_type.data_type).is_subtype_of (codegen.gobject_type)) || prop.property_type.data_type is Interface) { + string param_spec_name = prop.property_type.data_type.get_param_spec_function (); + if ( param_spec_name == null ) { + cspec.call = new CCodeIdentifier ("g_param_spec_pointer"); + } else { + cspec.call = new CCodeIdentifier ( param_spec_name ); + cspec.add_argument (new CCodeIdentifier (prop.property_type.data_type.get_type_id ())); + } } else if (prop.property_type.data_type == codegen.string_type.data_type) { cspec.call = new CCodeIdentifier ("g_param_spec_string"); cspec.add_argument (new CCodeConstant ("NULL")); diff --git a/gobject/valaclassregisterfunction.vala b/gobject/valaclassregisterfunction.vala index 7c6d84daf..d16222bcb 100644 --- a/gobject/valaclassregisterfunction.vala +++ b/gobject/valaclassregisterfunction.vala @@ -30,7 +30,7 @@ public class Vala.ClassRegisterFunction : TypeRegisterFunction { * Specifies the class to be registered. */ public weak Class class_reference { get; set; } - + /** * Creates a new C function to register the specified class at runtime. * @@ -86,6 +86,54 @@ public class Vala.ClassRegisterFunction : TypeRegisterFunction { return class_reference.access; } + public override string? get_gtype_value_table_init_function_name () { + bool is_fundamental = !class_reference.is_compact && !class_reference.is_static && class_reference.base_class == null; + if ( is_fundamental ) + return "%svalue_%s_init".printf(class_reference.parent_symbol.get_lower_case_cprefix (), class_reference.name.down() ); + + return null; + } + + public override string? get_gtype_value_table_free_function_name () { + bool is_fundamental = !class_reference.is_compact && !class_reference.is_static && class_reference.base_class == null; + if ( is_fundamental ) + return "%svalue_%s_free_value".printf(class_reference.parent_symbol.get_lower_case_cprefix (), class_reference.name.down() ); + + return null; + } + + public override string? get_gtype_value_table_copy_function_name () { + bool is_fundamental = !class_reference.is_compact && !class_reference.is_static && class_reference.base_class == null; + if ( is_fundamental ) + return "%svalue_%s_copy_value".printf(class_reference.parent_symbol.get_lower_case_cprefix (), class_reference.name.down() ); + + return null; + } + + public override string? get_gtype_value_table_peek_pointer_function_name () { + bool is_fundamental = !class_reference.is_compact && !class_reference.is_static && class_reference.base_class == null; + if ( is_fundamental ) + return "%svalue_%s_peek_pointer".printf(class_reference.parent_symbol.get_lower_case_cprefix (), class_reference.name.down() ); + + return null; + } + + public override string? get_gtype_value_table_collect_value_function_name () { + bool is_fundamental = !class_reference.is_compact && !class_reference.is_static && class_reference.base_class == null; + if ( is_fundamental ) + return "%svalue_%s_collect_value".printf(class_reference.parent_symbol.get_lower_case_cprefix (), class_reference.name.down() ); + + return null; + } + + public override string? get_gtype_value_table_lcopy_value_function_name () { + bool is_fundamental = !class_reference.is_compact && !class_reference.is_static && class_reference.base_class == null; + if ( is_fundamental ) + return "%svalue_%s_lcopy_value".printf(class_reference.parent_symbol.get_lower_case_cprefix (), class_reference.name.down() ); + + return null; + } + public override CCodeFragment get_type_interface_init_declaration () { var frag = new CCodeFragment (); diff --git a/gobject/valatyperegisterfunction.vala b/gobject/valatyperegisterfunction.vala index eba04f052..c26dc9519 100644 --- a/gobject/valatyperegisterfunction.vala +++ b/gobject/valatyperegisterfunction.vala @@ -89,10 +89,25 @@ public abstract class Vala.TypeRegisterFunction { definition_fragment.append (get_fun); } + string type_value_table_decl_name = null; var type_init = new CCodeBlock (); + + if ( fundamental ) { + var cgtypetabledecl = new CCodeDeclaration ("const GTypeValueTable"); + cgtypetabledecl.modifiers = CCodeModifiers.STATIC; + + cgtypetabledecl.add_declarator ( new CCodeVariableDeclarator.with_initializer ( "g_define_type_value_table", new CCodeConstant ("{ %s, %s, %s, %s, \"p\", %s, \"p\", %s }".printf ( get_gtype_value_table_init_function_name (), get_gtype_value_table_free_function_name (), get_gtype_value_table_copy_function_name (), get_gtype_value_table_peek_pointer_function_name (), get_gtype_value_table_collect_value_function_name (), get_gtype_value_table_lcopy_value_function_name () )))); + type_value_table_decl_name = "&g_define_type_value_table"; + type_init.add_statement ( cgtypetabledecl ); + } + else { + type_value_table_decl_name = "NULL"; + } + + var ctypedecl = new CCodeDeclaration ("const GTypeInfo"); ctypedecl.modifiers = CCodeModifiers.STATIC; - ctypedecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("g_define_type_info", new CCodeConstant ("{ sizeof (%s), (GBaseInitFunc) %s, (GBaseFinalizeFunc) NULL, (GClassInitFunc) %s, (GClassFinalizeFunc) NULL, NULL, %s, 0, (GInstanceInitFunc) %s }".printf (get_type_struct_name (), get_base_init_func_name (), get_class_init_func_name (), get_instance_struct_size (), get_instance_init_func_name ())))); + ctypedecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("g_define_type_info", new CCodeConstant ("{ sizeof (%s), (GBaseInitFunc) %s, (GBaseFinalizeFunc) NULL, (GClassInitFunc) %s, (GClassFinalizeFunc) NULL, NULL, %s, 0, (GInstanceInitFunc) %s, %s }".printf (get_type_struct_name (), get_base_init_func_name (), get_class_init_func_name (), get_instance_struct_size (), get_instance_init_func_name (), type_value_table_decl_name)))); type_init.add_statement (ctypedecl); if (fundamental) { var ctypefundamentaldecl = new CCodeDeclaration ("const GTypeFundamentalInfo"); @@ -215,10 +230,66 @@ public abstract class Vala.TypeRegisterFunction { /** * Returns the name of the parent type in C code. * - * @return C parent type name + * @return C function name */ public abstract string get_parent_type_name (); + + + /** + * Returns the C-name of the new generated GTypeValueTable init function or null when not available. + * + * @return C function name + */ + public virtual string? get_gtype_value_table_init_function_name () { + return null; + } + + /** + * Returns the C-name of the new generated GTypeValueTable peek pointer function or null when not available. + * + * @return C function name + */ + public virtual string? get_gtype_value_table_peek_pointer_function_name () { + return null; + } + + /** + * Returns the C-name of the new generated GTypeValueTable free function or null when not available. + * + * @return C function name + */ + public virtual string? get_gtype_value_table_free_function_name () { + return null; + } + + /** + * Returns the C-name of the new generated GTypeValueTable copy function or null when not available. + * + * @return C function name + */ + public virtual string? get_gtype_value_table_copy_function_name () { + return null; + } + + /** + * Returns the C-name of the new generated GTypeValueTable lcopy function or null when not available. + * + * @return C function name + */ + public virtual string? get_gtype_value_table_lcopy_value_function_name () { + return null; + } + + /** + * Returns the C-name of the new generated GTypeValueTable collect value function or null when not available. + * + * @return C function name + */ + public virtual string? get_gtype_value_table_collect_value_function_name () { + return null; + } + /** * Returns the set of type flags to be applied when registering. * diff --git a/vala/valaclass.vala b/vala/valaclass.vala index 82681f340..52e42a414 100644 --- a/vala/valaclass.vala +++ b/vala/valaclass.vala @@ -95,6 +95,7 @@ public class Vala.Class : ObjectTypeSymbol { private string type_id; private string ref_function; private string unref_function; + private string param_spec_function; private string copy_function; private string free_function; private string marshaller_type_name; @@ -626,8 +627,12 @@ public class Vala.Class : ObjectTypeSymbol { if (a.has_argument ("type_check_function")) { type_check_function = a.get_string ("type_check_function"); } + + if (a.has_argument ("param_spec_function")) { + param_spec_function = a.get_string ("param_spec_function"); + } } - + /** * Process all associated attributes. */ @@ -673,9 +678,25 @@ public class Vala.Class : ObjectTypeSymbol { return marshaller_type_name; } + public override string? get_param_spec_function () { + if (param_spec_function == null ) { + if (!(is_compact || base_class == null)) { + param_spec_function = base_class.get_param_spec_function (); + } + } + + return param_spec_function; + } + + public void set_param_spec_function ( string name ) { + param_spec_function = name; + } + public override string? get_get_value_function () { if (get_value_function == null) { - if (base_class != null) { + if (is_fundamental()) { + get_value_function = "%svalue_get_%s".printf(parent_symbol.get_lower_case_cprefix (), name.down()); + } else if (base_class != null) { get_value_function = base_class.get_get_value_function (); } else { get_value_function = "g_value_get_pointer"; @@ -687,7 +708,9 @@ public class Vala.Class : ObjectTypeSymbol { public override string? get_set_value_function () { if (set_value_function == null) { - if (base_class != null) { + if (is_fundamental()) { + set_value_function = "%svalue_set_%s".printf(parent_symbol.get_lower_case_cprefix (), name.down()); + } else if (base_class != null) { set_value_function = base_class.get_set_value_function (); } else { set_value_function = "g_value_set_pointer"; @@ -701,7 +724,7 @@ public class Vala.Class : ObjectTypeSymbol { return get_ref_function () != null; } - bool is_fundamental () { + public bool is_fundamental () { if (!is_compact && base_class == null) { return true; } diff --git a/vala/valainterfacewriter.vala b/vala/valainterfacewriter.vala index d9d750086..4c65b02aa 100644 --- a/vala/valainterfacewriter.vala +++ b/vala/valainterfacewriter.vala @@ -141,6 +141,10 @@ public class Vala.InterfaceWriter : CodeVisitor { write_string ("type_check_function = \"%s\", ".printf (cl.type_check_function )); } + if (cl.get_param_spec_function () != null) { + write_string ("param_spec_function = \"%s\", ".printf ( cl.get_param_spec_function () )); + } + bool first = true; string cheaders; foreach (string cheader in cl.get_cheader_filenames ()) { diff --git a/vala/valatypesymbol.vala b/vala/valatypesymbol.vala index fa43d0f6a..a838017f7 100644 --- a/vala/valatypesymbol.vala +++ b/vala/valatypesymbol.vala @@ -150,16 +150,23 @@ public abstract class Vala.TypeSymbol : Symbol { public virtual string? get_marshaller_type_name () { return null; } - + + /** + * Returns the cname of the GValue parameter spec function. + */ + public virtual string? get_param_spec_function () { + return null; + } + /** - * Returns the cname of the GValue getter function, + * Returns the cname of the GValue getter function. */ public virtual string? get_get_value_function () { return null; } /** - * Returns the cname of the GValue setter function, + * Returns the cname of the GValue setter function. */ public virtual string? get_set_value_function () { return null; diff --git a/vapi/glib-2.0.vapi b/vapi/glib-2.0.vapi index a27ebb7b3..cd081b52a 100644 --- a/vapi/glib-2.0.vapi +++ b/vapi/glib-2.0.vapi @@ -936,7 +936,7 @@ namespace GLib { public static delegate void ObjectSetPropertyFunc (Object object, uint property_id, Value value, ParamSpec pspec); public static delegate void WeakNotify (void *data, Object object); - [CCode (ref_function = "g_object_ref", unref_function = "g_object_unref", marshaller_type_name = "OBJECT", get_value_function = "g_value_get_object", set_value_function = "g_value_set_object", cheader_filename = "glib-object.h")] + [CCode (ref_function = "g_object_ref", unref_function = "g_object_unref", marshaller_type_name = "OBJECT", get_value_function = "g_value_get_object", set_value_function = "g_value_set_object", param_spec_function = "g_param_spec_object", cheader_filename = "glib-object.h")] public class Object : TypeInstance { public uint ref_count;