<commit_before>/* valagtypemodule.vala
 *
 * Copyright (C) 2006-2010  <NAME>
 * Copyright (C) 2006-2008  <NAME>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.

 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 *
 * Author:
 * 	<NAME> <<EMAIL>>
 *	<NAME> <<EMAIL>>
 */


public class Vala.GTypeModule : GErrorModule {
	public override void generate_parameter (FormalParameter param, CCodeDeclarationSpace decl_space, Map<int,CCodeFormalParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
		if (!(param.variable_type is ObjectType)) {
			base.generate_parameter (param, decl_space, cparam_map, carg_map);
			return;
		}

		generate_type_declaration (param.variable_type, decl_space);

		string ctypename = param.variable_type.get_cname ();

		if (param.direction != ParameterDirection.IN) {
			ctypename += "*";
		}

		param.ccodenode = new CCodeFormalParameter (get_variable_cname (param.name), ctypename);

		cparam_map.set (get_param_pos (param.cparameter_position), (CCodeFormalParameter) param.ccodenode);
		if (carg_map != null) {
			carg_map.set (get_param_pos (param.cparameter_position), get_variable_cexpression (param.name));
		}
	}

	public override void generate_class_declaration (Class cl, CCodeDeclarationSpace decl_space) {
		if (decl_space.add_symbol_declaration (cl, cl.get_cname ())) {
			return;
		}

		if (cl.base_class != null) {
			// base class declaration
			// necessary for ref and unref function declarations
			generate_class_declaration (cl.base_class, decl_space);
		}

		bool is_gtypeinstance = !cl.is_compact;
		bool is_fundamental = is_gtypeinstance && cl.base_class == null;

		if (is_gtypeinstance) {
			decl_space.add_type_declaration (new CCodeNewline ());
			var macro = "(%s_get_type ())".printf (cl.get_lower_case_cname (null));
			decl_space.add_type_declaration (new CCodeMacroReplacement (cl.get_type_id (), macro));

			macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (cl.get_type_id (), cl.get_cname ());
			decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (cl.get_upper_case_cname (null)), macro));

			macro = "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %sClass))".printf (cl.get_type_id (), cl.get_cname ());
			decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (cl.get_upper_case_cname (null)), macro));

			macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (cl.get_type_id ());
			decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_type_check_function (cl)), macro));

			macro = "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (cl.get_type_id ());
			decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (get_type_check_function (cl)), macro));

			macro = "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %sClass))".printf (cl.get_type_id (), cl.get_cname ());
			decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_GET_CLASS(obj)".printf (cl.get_upper_case_cname (null)), macro));
			decl_space.add_type_declaration (new CCodeNewline ());
		}

		if (cl.is_compact && cl.base_class != null) {
			decl_space.add_type_declaration (new CCodeTypeDefinition (cl.base_class.get_cname (), new CCodeVariableDeclarator (cl.get_cname ())));
		} else {
			decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (cl.get_cname ()), new CCodeVariableDeclarator (cl.get_cname ())));
		}

		if (is_fundamental) {
			var ref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "ref", "gpointer");
			var unref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "unref", "void");
			if (cl.access == SymbolAccessibility.PRIVATE) {
				ref_fun.modifiers = CCodeModifiers.STATIC;
				unref_fun.modifiers = CCodeModifiers.STATIC;
			}

			ref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer"));
			unref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer"));

			decl_space.add_type_member_declaration (ref_fun.copy ());
			decl_space.add_type_member_declaration (unref_fun.copy ());

			// GParamSpec and GValue functions
			string function_name = cl.get_lower_case_cname ("param_spec_");

			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"));

			if (cl.access == SymbolAccessibility.PRIVATE) {
				function.modifiers = CCodeModifiers.STATIC;
				// avoid C warning as this function is not always used
				function.attributes = "G_GNUC_UNUSED";
			}

			decl_space.add_type_member_declaration (function);

			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;
				// avoid C warning as this function is not always used
				function.attributes = "G_GNUC_UNUSED";
			}

			decl_space.add_type_member_declaration (function);

			function = new CCodeFunction (cl.get_take_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;
				// avoid C warning as this function is not always used
				function.attributes = "G_GNUC_UNUSED";
			}

			decl_space.add_type_member_declaration (function);

			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;
				// avoid C warning as this function is not always used
				function.attributes = "G_GNUC_UNUSED";
			}

			decl_space.add_type_member_declaration (function);
		} else if (!is_gtypeinstance) {
			if (cl.base_class == null) {
				var function = new CCodeFunction (cl.get_lower_case_cprefix () + "free", "void");
				if (cl.access == SymbolAccessibility.PRIVATE) {
					function.modifiers = CCodeModifiers.STATIC;
				}

				function.add_parameter (new CCodeFormalParameter ("self", cl.get_cname () + "*"));

				decl_space.add_type_member_declaration (function);
			}
		}

		if (is_gtypeinstance) {
			decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%sClass".printf (cl.get_cname ()), new CCodeVariableDeclarator ("%sClass".printf (cl.get_cname ()))));

			var type_fun = new ClassRegisterFunction (cl, context);
			type_fun.init_from_type (in_plugin);
			decl_space.add_type_member_declaration (type_fun.get_declaration ());
		}
	}

	public override void generate_class_struct_declaration (Class cl, CCodeDeclarationSpace decl_space) {
		if (decl_space.add_symbol_declaration (cl, "struct _" + cl.get_cname ())) {
			return;
		}

		if (cl.base_class != null) {
			// base class declaration
			generate_class_struct_declaration (cl.base_class, decl_space);
		}
		foreach (DataType base_type in cl.get_base_types ()) {
			var iface = base_type.data_type as Interface;
			if (iface != null) {
				generate_interface_declaration (iface, decl_space);
			}
		}

		generate_class_declaration (cl, decl_space);

		bool is_gtypeinstance = !cl.is_compact;
		bool is_fundamental = is_gtypeinstance && cl.base_class == null;

		var instance_struct = new CCodeStruct ("_%s".printf (cl.get_cname ()));
		var type_struct = new CCodeStruct ("_%sClass".printf (cl.get_cname ()));

		if (cl.base_class != null) {
			instance_struct.add_field (cl.base_class.get_cname (), "parent_instance");
		} else if (is_fundamental) {
			decl_space.add_include ("glib-object.h");
			instance_struct.add_field ("GTypeInstance", "parent_instance");
			instance_struct.add_field ("volatile int", "ref_count");
		}

		if (cl.is_compact && cl.base_class == null && cl.get_fields ().size == 0) {
			// add dummy member, C doesn't allow empty structs
			instance_struct.add_field ("int", "dummy");
		}

		if (is_gtypeinstance) {
			decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %sPrivate".printf (instance_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (cl.get_cname ()))));

			instance_struct.add_field ("%sPrivate *".printf (cl.get_cname ()), "priv");
			if (is_fundamental) {
				type_struct.add_field ("GTypeClass", "parent_class");
			} else {
				type_struct.add_field ("%sClass".printf (cl.base_class.get_cname ()), "parent_class");
			}

			if (is_fundamental) {
				type_struct.add_field ("void", "(*finalize) (%s *self)".printf (cl.get_cname ()));
			}
		}

		foreach (Method m in cl.get_methods ()) {
			generate_virtual_method_declaration (m, decl_space, type_struct);
		}

		foreach (Signal sig in cl.get_signals ()) {
			if (sig.default_handler != null) {
				generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
			}
		}

		foreach (Property prop in cl.get_properties ()) {
			if (!prop.is_abstract && !prop.is_virtual) {
				continue;
			}
			generate_type_declaration (prop.property_type, decl_space);

			var t = (ObjectTypeSymbol) prop.parent_symbol;

			var this_type = new ObjectType (t);
			var cselfparam = new CCodeFormalParameter ("self", this_type.get_cname ());

			if (prop.get_accessor != null) {
				var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name));
				vdeclarator.add_parameter (cselfparam);
				string creturn_type;
				if (prop.property_type.is_real_non_null_struct_type ()) {
					var cvalueparam = new CCodeFormalParameter ("result", prop.get_accessor.value_type.get_cname () + "*");
					vdeclarator.add_parameter (cvalueparam);
					creturn_type = "void";
				} else {
					creturn_type = prop.get_accessor.value_type.get_cname ();
				}

				var array_type = prop.property_type as ArrayType;
				if (array_type != null) {
					for (int dim = 1; dim <= array_type.rank; dim++) {
						vdeclarator.add_parameter (new CCodeFormalParameter (get_array_length_cname ("result", dim), "int*"));
					}
				} else if ((prop.property_type is DelegateType) && ((DelegateType) prop.property_type).delegate_symbol.has_target) {
					vdeclarator.add_parameter (new CCodeFormalParameter (get_delegate_target_cname ("result"), "gpointer*"));
				}

				var vdecl = new CCodeDeclaration (creturn_type);
				vdecl.add_declarator (vdeclarator);
				type_struct.add_declaration (vdecl);
			}
			if (prop.set_accessor != null) {
				CCodeFormalParameter cvalueparam;
				if (prop.property_type.is_real_non_null_struct_type ()) {
					cvalueparam = new CCodeFormalParameter ("value", prop.set_accessor.value_type.get_cname () + "*");
				} else {
					cvalueparam = new CCodeFormalParameter ("value", prop.set_accessor.value_type.get_cname ());
				}

				var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name));
				vdeclarator.add_parameter (cselfparam);
				vdeclarator.add_parameter (cvalueparam);

				var array_type = prop.property_type as ArrayType;
				if (array_type != null) {
					for (int dim = 1; dim <= array_type.rank; dim++) {
						vdeclarator.add_parameter (new CCodeFormalParameter (get_array_length_cname ("value", dim), "int"));
					}
				} else if ((prop.property_type is DelegateType) && ((DelegateType) prop.property_type).delegate_symbol.has_target) {
					vdeclarator.add_parameter (new CCodeFormalParameter (get_delegate_target_cname ("value"), "gpointer"));
				}

				var vdecl = new CCodeDeclaration ("void");
				vdecl.add_declarator (vdeclarator);
				type_struct.add_declaration (vdecl);
			}
		}

		foreach (Field f in cl.get_fields ()) {
			string field_ctype = f.variable_type.get_cname ();
			if (f.is_volatile) {
				field_ctype = "volatile " + field_ctype;
			}

			if (f.access != SymbolAccessibility.PRIVATE) {
				if (f.binding == MemberBinding.INSTANCE) {
					generate_type_declaration (f.variable_type, decl_space);

					instance_struct.add_field (field_ctype, f.get_cname (), f.variable_type.get_cdeclarator_suffix ());
					if (f.variable_type is ArrayType && !f.no_array_length) {
						// create fields to store array dimensions
						var array_type = (ArrayType) f.variable_type;

						if (!array_type.fixed_length) {
							var len_type = int_type.copy ();

							for (int dim = 1; dim <= array_type.rank; dim++) {
								instance_struct.add_field (len_type.get_cname (), get_array_length_cname (f.name, dim));
							}

							if (array_type.rank == 1 && f.is_internal_symbol ()) {
								instance_struct.add_field (len_type.get_cname (), get_array_size_cname (f.name));
							}
						}
					} else if (f.variable_type is DelegateType) {
						var delegate_type = (DelegateType) f.variable_type;
						if (delegate_type.delegate_symbol.has_target) {
							// create field to store delegate target
							instance_struct.add_field ("gpointer", get_delegate_target_cname (f.name));
							if (delegate_type.value_owned) {
								instance_struct.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (f.name));
							}
						}
					}
				} else if (f.binding == MemberBinding.CLASS) {
					type_struct.add_field (field_ctype, f.get_cname ());
				}
			}
		}

		if (!cl.is_compact || cl.base_class == null) {
			// derived compact classes do not have a struct
			decl_space.add_type_definition (instance_struct);
		}

		if (is_gtypeinstance) {
			decl_space.add_type_definition (type_struct);
		}
	}

	public virtual void generate_virtual_method_declaration (Method m, CCodeDeclarationSpace decl_space, CCodeStruct type_struct) {
		if (!m.is_abstract && !m.is_virtual) {
			return;
		}

		var creturn_type = m.return_type;
		if (m.return_type.is_real_non_null_struct_type ()) {
			// structs are returned via out parameter
			creturn_type = new VoidType ();
		}

		// add vfunc field to the type struct
		var vdeclarator = new CCodeFunctionDeclarator (m.vfunc_name);
		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);

		generate_cparameters (m, decl_space, cparam_map, new CCodeFunction ("fake"), vdeclarator);

		var vdecl = new CCodeDeclaration (creturn_type.get_cname ());
		vdecl.add_declarator (vdeclarator);
		type_struct.add_declaration (vdecl);
	}

	void generate_class_private_declaration (Class cl, CCodeDeclarationSpace decl_space) {
		if (decl_space.add_declaration (cl.get_cname () + "Private")) {
			return;
		}

		bool is_gtypeinstance = !cl.is_compact;
		bool has_instance_locks = false;
		bool has_class_locks = false;

		var instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (cl.get_cname ()));
		var type_priv_struct = new CCodeStruct ("_%sClassPrivate".printf (cl.get_cname ()));

		if (is_gtypeinstance) {
			/* create type, dup_func, and destroy_func fields for generic types */
			foreach (TypeParameter type_param in cl.get_type_parameters ()) {
				string func_name;

				func_name = "%s_type".printf (type_param.name.down ());
				instance_priv_struct.add_field ("GType", func_name);

				func_name = "%s_dup_func".printf (type_param.name.down ());
				instance_priv_struct.add_field ("GBoxedCopyFunc", func_name);

				func_name = "%s_destroy_func".printf (type_param.name.down ());
				instance_priv_struct.add_field ("GDestroyNotify", func_name);
			}
		}

		foreach (Field f in cl.get_fields ()) {
			string field_ctype = f.variable_type.get_cname ();
			if (f.is_volatile) {
				field_ctype = "volatile " + field_ctype;
			}

			if (f.binding == MemberBinding.INSTANCE) {
				if (f.access == SymbolAccessibility.PRIVATE)  {
					generate_type_declaration (f.variable_type, decl_space);

					instance_priv_struct.add_field (field_ctype, f.get_cname (), f.variable_type.get_cdeclarator_suffix ());
					if (f.variable_type is ArrayType && !f.no_array_length) {
						// create fields to store array dimensions
						var array_type = (ArrayType) f.variable_type;
						var len_type = int_type.copy ();

						if (!array_type.fixed_length) {
							for (int dim = 1; dim <= array_type.rank; dim++) {
								instance_priv_struct.add_field (len_type.get_cname (), get_array_length_cname (f.name, dim));
							}

							if (array_type.rank == 1 && f.is_internal_symbol ()) {
								instance_priv_struct.add_field (len_type.get_cname (), get_array_size_cname (f.name));
							}
						}
					} else if (f.variable_type is DelegateType) {
						var delegate_type = (DelegateType) f.variable_type;
						if (delegate_type.delegate_symbol.has_target) {
							// create field to store delegate target
							instance_priv_struct.add_field ("gpointer", get_delegate_target_cname (f.name));
							if (delegate_type.value_owned) {
								instance_priv_struct.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (f.name));
							}
						}
					}
				}

				if (f.get_lock_used ()) {
					has_instance_locks = true;
					// add field for mutex
					instance_priv_struct.add_field (mutex_type.get_cname (), get_symbol_lock_name (f.name));
				}
			} else if (f.binding == MemberBinding.CLASS) {
				if (f.access == SymbolAccessibility.PRIVATE) {
					type_priv_struct.add_field (field_ctype, f.get_cname ());
				}

				if (f.get_lock_used ()) {
					has_class_locks = true;
					// add field for mutex
					type_priv_struct.add_field (mutex_type.get_cname (), get_symbol_lock_name (f.get_cname ()));
				}
			}
		}

		if (is_gtypeinstance) {
			if (cl.has_class_private_fields || has_class_locks) {
				decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_priv_struct.name), new CCodeVariableDeclarator ("%sClassPrivate".printf (cl.get_cname ()))));
				if (!context.require_glib_version (2, 24)) {
					var cdecl = new CCodeDeclaration ("GQuark");
					cdecl.add_declarator (new CCodeVariableDeclarator ("_vala_%s_class_private_quark".printf (cl.get_lower_case_cname ()), new CCodeConstant ("0")));
					cdecl.modifiers = CCodeModifiers.STATIC;<commit_msg>Add mutex field in priv structures for properties<commit_after>/* valagtypemodule.vala
 *
 * Copyright (C) 2006-2010  <NAME>
 * Copyright (C) 2006-2008  <NAME>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.

 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 *
 * Author:
 * 	<NAME> <<EMAIL>>
 *	<NAME> <<EMAIL>>
 */


public class Vala.GTypeModule : GErrorModule {
	public override void generate_parameter (FormalParameter param, CCodeDeclarationSpace decl_space, Map<int,CCodeFormalParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
		if (!(param.variable_type is ObjectType)) {
			base.generate_parameter (param, decl_space, cparam_map, carg_map);
			return;
		}

		generate_type_declaration (param.variable_type, decl_space);

		string ctypename = param.variable_type.get_cname ();

		if (param.direction != ParameterDirection.IN) {
			ctypename += "*";
		}

		param.ccodenode = new CCodeFormalParameter (get_variable_cname (param.name), ctypename);

		cparam_map.set (get_param_pos (param.cparameter_position), (CCodeFormalParameter) param.ccodenode);
		if (carg_map != null) {
			carg_map.set (get_param_pos (param.cparameter_position), get_variable_cexpression (param.name));
		}
	}

	public override void generate_class_declaration (Class cl, CCodeDeclarationSpace decl_space) {
		if (decl_space.add_symbol_declaration (cl, cl.get_cname ())) {
			return;
		}

		if (cl.base_class != null) {
			// base class declaration
			// necessary for ref and unref function declarations
			generate_class_declaration (cl.base_class, decl_space);
		}

		bool is_gtypeinstance = !cl.is_compact;
		bool is_fundamental = is_gtypeinstance && cl.base_class == null;

		if (is_gtypeinstance) {
			decl_space.add_type_declaration (new CCodeNewline ());
			var macro = "(%s_get_type ())".printf (cl.get_lower_case_cname (null));
			decl_space.add_type_declaration (new CCodeMacroReplacement (cl.get_type_id (), macro));

			macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (cl.get_type_id (), cl.get_cname ());
			decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (cl.get_upper_case_cname (null)), macro));

			macro = "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %sClass))".printf (cl.get_type_id (), cl.get_cname ());
			decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (cl.get_upper_case_cname (null)), macro));

			macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (cl.get_type_id ());
			decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_type_check_function (cl)), macro));

			macro = "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (cl.get_type_id ());
			decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (get_type_check_function (cl)), macro));

			macro = "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %sClass))".printf (cl.get_type_id (), cl.get_cname ());
			decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_GET_CLASS(obj)".printf (cl.get_upper_case_cname (null)), macro));
			decl_space.add_type_declaration (new CCodeNewline ());
		}

		if (cl.is_compact && cl.base_class != null) {
			decl_space.add_type_declaration (new CCodeTypeDefinition (cl.base_class.get_cname (), new CCodeVariableDeclarator (cl.get_cname ())));
		} else {
			decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (cl.get_cname ()), new CCodeVariableDeclarator (cl.get_cname ())));
		}

		if (is_fundamental) {
			var ref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "ref", "gpointer");
			var unref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "unref", "void");
			if (cl.access == SymbolAccessibility.PRIVATE) {
				ref_fun.modifiers = CCodeModifiers.STATIC;
				unref_fun.modifiers = CCodeModifiers.STATIC;
			}

			ref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer"));
			unref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer"));

			decl_space.add_type_member_declaration (ref_fun.copy ());
			decl_space.add_type_member_declaration (unref_fun.copy ());

			// GParamSpec and GValue functions
			string function_name = cl.get_lower_case_cname ("param_spec_");

			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"));

			if (cl.access == SymbolAccessibility.PRIVATE) {
				function.modifiers = CCodeModifiers.STATIC;
				// avoid C warning as this function is not always used
				function.attributes = "G_GNUC_UNUSED";
			}

			decl_space.add_type_member_declaration (function);

			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;
				// avoid C warning as this function is not always used
				function.attributes = "G_GNUC_UNUSED";
			}

			decl_space.add_type_member_declaration (function);

			function = new CCodeFunction (cl.get_take_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;
				// avoid C warning as this function is not always used
				function.attributes = "G_GNUC_UNUSED";
			}

			decl_space.add_type_member_declaration (function);

			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;
				// avoid C warning as this function is not always used
				function.attributes = "G_GNUC_UNUSED";
			}

			decl_space.add_type_member_declaration (function);
		} else if (!is_gtypeinstance) {
			if (cl.base_class == null) {
				var function = new CCodeFunction (cl.get_lower_case_cprefix () + "free", "void");
				if (cl.access == SymbolAccessibility.PRIVATE) {
					function.modifiers = CCodeModifiers.STATIC;
				}

				function.add_parameter (new CCodeFormalParameter ("self", cl.get_cname () + "*"));

				decl_space.add_type_member_declaration (function);
			}
		}

		if (is_gtypeinstance) {
			decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%sClass".printf (cl.get_cname ()), new CCodeVariableDeclarator ("%sClass".printf (cl.get_cname ()))));

			var type_fun = new ClassRegisterFunction (cl, context);
			type_fun.init_from_type (in_plugin);
			decl_space.add_type_member_declaration (type_fun.get_declaration ());
		}
	}

	public override void generate_class_struct_declaration (Class cl, CCodeDeclarationSpace decl_space) {
		if (decl_space.add_symbol_declaration (cl, "struct _" + cl.get_cname ())) {
			return;
		}

		if (cl.base_class != null) {
			// base class declaration
			generate_class_struct_declaration (cl.base_class, decl_space);
		}
		foreach (DataType base_type in cl.get_base_types ()) {
			var iface = base_type.data_type as Interface;
			if (iface != null) {
				generate_interface_declaration (iface, decl_space);
			}
		}

		generate_class_declaration (cl, decl_space);

		bool is_gtypeinstance = !cl.is_compact;
		bool is_fundamental = is_gtypeinstance && cl.base_class == null;

		var instance_struct = new CCodeStruct ("_%s".printf (cl.get_cname ()));
		var type_struct = new CCodeStruct ("_%sClass".printf (cl.get_cname ()));

		if (cl.base_class != null) {
			instance_struct.add_field (cl.base_class.get_cname (), "parent_instance");
		} else if (is_fundamental) {
			decl_space.add_include ("glib-object.h");
			instance_struct.add_field ("GTypeInstance", "parent_instance");
			instance_struct.add_field ("volatile int", "ref_count");
		}

		if (cl.is_compact && cl.base_class == null && cl.get_fields ().size == 0) {
			// add dummy member, C doesn't allow empty structs
			instance_struct.add_field ("int", "dummy");
		}

		if (is_gtypeinstance) {
			decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %sPrivate".printf (instance_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (cl.get_cname ()))));

			instance_struct.add_field ("%sPrivate *".printf (cl.get_cname ()), "priv");
			if (is_fundamental) {
				type_struct.add_field ("GTypeClass", "parent_class");
			} else {
				type_struct.add_field ("%sClass".printf (cl.base_class.get_cname ()), "parent_class");
			}

			if (is_fundamental) {
				type_struct.add_field ("void", "(*finalize) (%s *self)".printf (cl.get_cname ()));
			}
		}

		foreach (Method m in cl.get_methods ()) {
			generate_virtual_method_declaration (m, decl_space, type_struct);
		}

		foreach (Signal sig in cl.get_signals ()) {
			if (sig.default_handler != null) {
				generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
			}
		}

		foreach (Property prop in cl.get_properties ()) {
			if (!prop.is_abstract && !prop.is_virtual) {
				continue;
			}
			generate_type_declaration (prop.property_type, decl_space);

			var t = (ObjectTypeSymbol) prop.parent_symbol;

			var this_type = new ObjectType (t);
			var cselfparam = new CCodeFormalParameter ("self", this_type.get_cname ());

			if (prop.get_accessor != null) {
				var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name));
				vdeclarator.add_parameter (cselfparam);
				string creturn_type;
				if (prop.property_type.is_real_non_null_struct_type ()) {
					var cvalueparam = new CCodeFormalParameter ("result", prop.get_accessor.value_type.get_cname () + "*");
					vdeclarator.add_parameter (cvalueparam);
					creturn_type = "void";
				} else {
					creturn_type = prop.get_accessor.value_type.get_cname ();
				}

				var array_type = prop.property_type as ArrayType;
				if (array_type != null) {
					for (int dim = 1; dim <= array_type.rank; dim++) {
						vdeclarator.add_parameter (new CCodeFormalParameter (get_array_length_cname ("result", dim), "int*"));
					}
				} else if ((prop.property_type is DelegateType) && ((DelegateType) prop.property_type).delegate_symbol.has_target) {
					vdeclarator.add_parameter (new CCodeFormalParameter (get_delegate_target_cname ("result"), "gpointer*"));
				}

				var vdecl = new CCodeDeclaration (creturn_type);
				vdecl.add_declarator (vdeclarator);
				type_struct.add_declaration (vdecl);
			}
			if (prop.set_accessor != null) {
				CCodeFormalParameter cvalueparam;
				if (prop.property_type.is_real_non_null_struct_type ()) {
					cvalueparam = new CCodeFormalParameter ("value", prop.set_accessor.value_type.get_cname () + "*");
				} else {
					cvalueparam = new CCodeFormalParameter ("value", prop.set_accessor.value_type.get_cname ());
				}

				var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name));
				vdeclarator.add_parameter (cselfparam);
				vdeclarator.add_parameter (cvalueparam);

				var array_type = prop.property_type as ArrayType;
				if (array_type != null) {
					for (int dim = 1; dim <= array_type.rank; dim++) {
						vdeclarator.add_parameter (new CCodeFormalParameter (get_array_length_cname ("value", dim), "int"));
					}
				} else if ((prop.property_type is DelegateType) && ((DelegateType) prop.property_type).delegate_symbol.has_target) {
					vdeclarator.add_parameter (new CCodeFormalParameter (get_delegate_target_cname ("value"), "gpointer"));
				}

				var vdecl = new CCodeDeclaration ("void");
				vdecl.add_declarator (vdeclarator);
				type_struct.add_declaration (vdecl);
			}
		}

		foreach (Field f in cl.get_fields ()) {
			string field_ctype = f.variable_type.get_cname ();
			if (f.is_volatile) {
				field_ctype = "volatile " + field_ctype;
			}

			if (f.access != SymbolAccessibility.PRIVATE) {
				if (f.binding == MemberBinding.INSTANCE) {
					generate_type_declaration (f.variable_type, decl_space);

					instance_struct.add_field (field_ctype, f.get_cname (), f.variable_type.get_cdeclarator_suffix ());
					if (f.variable_type is ArrayType && !f.no_array_length) {
						// create fields to store array dimensions
						var array_type = (ArrayType) f.variable_type;

						if (!array_type.fixed_length) {
							var len_type = int_type.copy ();

							for (int dim = 1; dim <= array_type.rank; dim++) {
								instance_struct.add_field (len_type.get_cname (), get_array_length_cname (f.name, dim));
							}

							if (array_type.rank == 1 && f.is_internal_symbol ()) {
								instance_struct.add_field (len_type.get_cname (), get_array_size_cname (f.name));
							}
						}
					} else if (f.variable_type is DelegateType) {
						var delegate_type = (DelegateType) f.variable_type;
						if (delegate_type.delegate_symbol.has_target) {
							// create field to store delegate target
							instance_struct.add_field ("gpointer", get_delegate_target_cname (f.name));
							if (delegate_type.value_owned) {
								instance_struct.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (f.name));
							}
						}
					}
				} else if (f.binding == MemberBinding.CLASS) {
					type_struct.add_field (field_ctype, f.get_cname ());
				}
			}
		}

		if (!cl.is_compact || cl.base_class == null) {
			// derived compact classes do not have a struct
			decl_space.add_type_definition (instance_struct);
		}

		if (is_gtypeinstance) {
			decl_space.add_type_definition (type_struct);
		}
	}

	public virtual void generate_virtual_method_declaration (Method m, CCodeDeclarationSpace decl_space, CCodeStruct type_struct) {
		if (!m.is_abstract && !m.is_virtual) {
			return;
		}

		var creturn_type = m.return_type;
		if (m.return_type.is_real_non_null_struct_type ()) {
			// structs are returned via out parameter
			creturn_type = new VoidType ();
		}

		// add vfunc field to the type struct
		var vdeclarator = new CCodeFunctionDeclarator (m.vfunc_name);
		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);

		generate_cparameters (m, decl_space, cparam_map, new CCodeFunction ("fake"), vdeclarator);

		var vdecl = new CCodeDeclaration (creturn_type.get_cname ());
		vdecl.add_declarator (vdeclarator);
		type_struct.add_declaration (vdecl);
	}

	void generate_class_private_declaration (Class cl, CCodeDeclarationSpace decl_space) {
		if (decl_space.add_declaration (cl.get_cname () + "Private")) {
			return;
		}

		bool is_gtypeinstance = !cl.is_compact;
		bool has_instance_locks = false;
		bool has_class_locks = false;

		var instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (cl.get_cname ()));
		var type_priv_struct = new CCodeStruct ("_%sClassPrivate".printf (cl.get_cname ()));

		if (is_gtypeinstance) {
			/* create type, dup_func, and destroy_func fields for generic types */
			foreach (TypeParameter type_param in cl.get_type_parameters ()) {
				string func_name;

				func_name = "%s_type".printf (type_param.name.down ());
				instance_priv_struct.add_field ("GType", func_name);

				func_name = "%s_dup_func".printf (type_param.name.down ());
				instance_priv_struct.add_field ("GBoxedCopyFunc", func_name);

				func_name = "%s_destroy_func".printf (type_param.name.down ());
				instance_priv_struct.add_field ("GDestroyNotify", func_name);
			}
		}

		foreach (Field f in cl.get_fields ()) {
			string field_ctype = f.variable_type.get_cname ();
			if (f.is_volatile) {
				field_ctype = "volatile " + field_ctype;
			}

			if (f.binding == MemberBinding.INSTANCE) {
				if (f.access == SymbolAccessibility.PRIVATE)  {
					generate_type_declaration (f.variable_type, decl_space);

					instance_priv_struct.add_field (field_ctype, f.get_cname (), f.variable_type.get_cdeclarator_suffix ());
					if (f.variable_type is ArrayType && !f.no_array_length) {
						// create fields to store array dimensions
						var array_type = (ArrayType) f.variable_type;
						var len_type = int_type.copy ();

						if (!array_type.fixed_length) {
							for (int dim = 1; dim <= array_type.rank; dim++) {
								instance_priv_struct.add_field (len_type.get_cname (), get_array_length_cname (f.name, dim));
							}

							if (array_type.rank == 1 && f.is_internal_symbol ()) {
								instance_priv_struct.add_field (len_type.get_cname (), get_array_size_cname (f.name));
							}
						}
					} else if (f.variable_type is DelegateType) {
						var delegate_type = (DelegateType) f.variable_type;
						if (delegate_type.delegate_symbol.has_target) {
							// create field to store delegate target
							instance_priv_struct.add_field ("gpointer", get_delegate_target_cname (f.name));
							if (delegate_type.value_owned) {
								instance_priv_struct.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (f.name));
							}
						}
					}
				}

				if (f.get_lock_used ()) {
					has_instance_locks = true;
					// add field for mutex
					instance_priv_struct.add_field (mutex_type.get_cname (), get_symbol_lock_name (f.name));
				}
			} else if (f.binding == MemberBinding.CLASS) {
				if (f.access == SymbolAccessibility.PRIVATE) {
					type_priv_struct.add_field (field_ctype, f.get_cname ());
				}

				if (f.get_lock_used ()) {
					has_class_locks = true;
					// add field for mutex
					type_priv_struct.add_field (mutex_type.get_cname (), get_symbol_lock_name (f.get_cname ()));
				}
			}
		}

		foreach (Property prop in cl.get_properties ()) {
			if (prop.binding == MemberBinding.INSTANCE) {
				if (prop.get_lock_used ()) {
					has_instance_locks = true;
					// add field for mutex
					instance_priv_struct.add_field (mutex_type.get_cname (), get_symbol_lock_name (prop.name));
				}
			} else if (prop.binding == MemberBinding.CLASS) {
				if (prop.get_lock_used ()) {
					has_class_locks = true;
					// add field for mutex
					type_priv_struct.add_field (mutex_type.get_cname (), get_symbol_lock_name (prop.name));
				}
			}
		}

		if (is_gtypeinstance) {
			if (cl.has_class_private_fields || has_class_locks) {
				decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_priv_struct.name), new CCodeVariableDeclarator ("%sClassPrivate".printf (cl.get_cname ()))));
				if (!context.require_glib_version (2, 24)) {
					var cdecl = new CCodeDeclaration ("GQuark");
					cdecl.add_declarator (new CCodeVariableDeclarator ("_vala_%s_class_private_quark".printf (cl.get_lower_case_cname ()), new CCodeConstant ("0")));
					cdecl.modifiers = CCodeModifiers.STATIC;
{'fraction_non_alphanumeric': 0.12186613209757621, 'fraction_numerical': 0.002082736716044883, 'mean_word_length': 4.308457711442786, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6173113', 'n_tokens_mistral': 14841, 'n_tokens_neox': 12697, 'n_words': 2656}