Generate code to support GValue and GParamSpec for fundamental classes,
authorJürg Billeter <j@bitron.ch>
Fri, 3 Oct 2008 13:17:10 +0000 (13:17 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Fri, 3 Oct 2008 13:17:10 +0000 (13:17 +0000)
2008-10-03  Jürg Billeter  <j@bitron.ch>

* 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

ChangeLog
gobject/valaccodeclassbinding.vala
gobject/valaccodegenerator.vala
gobject/valaccodegeneratorsourcefile.vala
gobject/valaccodetypesymbolbinding.vala
gobject/valaclassregisterfunction.vala
gobject/valatyperegisterfunction.vala
vala/valaclass.vala
vala/valainterfacewriter.vala
vala/valatypesymbol.vala
vapi/glib-2.0.vapi

index f594ae0..35f422c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 2008-10-03  Jürg Billeter  <j@bitron.ch>
 
+       * 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  <j@bitron.ch>
+
        * vapi/glib-2.0.vapi:
 
        Add g_log_set_default_handler binding, patch by Marc-André Lureau,
index 10461e8..9d20fb0 100644 (file)
@@ -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;
                
index 5064ecf..7066d3b 100644 (file)
@@ -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;
index 4149d00..e9c38f8 100644 (file)
@@ -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"));
                }
index 939b109..1b991e3 100644 (file)
@@ -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"));
index 7c6d84d..d16222b 100644 (file)
@@ -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 ();
                
index eba04f0..c26dc95 100644 (file)
@@ -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.
         *
index 82681f3..52e42a4 100644 (file)
@@ -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;
                }
index d9d7500..4c65b02 100644 (file)
@@ -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 ()) {
index fa43d0f..a838017 100644 (file)
@@ -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;
index a27ebb7..cd081b5 100644 (file)
@@ -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;