1/* valaclassregisterfunction.vala
2 *
3 * Copyright (C) 2006-2008  Jürg Billeter
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * Lesser General Public License for more details.
14
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
18 *
19 * Author:
20 * 	Jürg Billeter <j@bitron.ch>
21 */
22
23using GLib;
24
25/**
26 * C function to register a class at runtime.
27 */
28public class Vala.ClassRegisterFunction : TypeRegisterFunction {
29	/**
30	 * Specifies the class to be registered.
31	 */
32	public weak Class class_reference { get; set; }
33
34	/**
35	 * Creates a new C function to register the specified class at runtime.
36	 *
37	 * @param cl a class
38	 * @return   newly created class register function
39	 */
40	public ClassRegisterFunction (Class cl) {
41		class_reference = cl;
42	}
43
44	public override TypeSymbol get_type_declaration () {
45		return class_reference;
46	}
47
48	public override string get_type_struct_name () {
49		return get_ccode_type_name (class_reference);
50	}
51
52	public override string get_base_init_func_name () {
53		if (class_reference.class_constructor != null) {
54			return "%s_base_init".printf (get_ccode_lower_case_name (class_reference, null));
55		} else {
56			return "NULL";
57		}
58	}
59
60	public override string get_class_finalize_func_name () {
61		if (class_reference.static_destructor != null) {
62			return "%s_class_finalize".printf (get_ccode_lower_case_name (class_reference, null));
63		} else {
64			return "NULL";
65		}
66	}
67
68	public override string get_base_finalize_func_name () {
69		if (class_reference.class_destructor != null) {
70			return "%s_base_finalize".printf (get_ccode_lower_case_name (class_reference, null));
71		} else {
72			return "NULL";
73		}
74	}
75
76	public override string get_class_init_func_name () {
77		return "%s_class_init".printf (get_ccode_lower_case_name (class_reference, null));
78	}
79
80	public override string get_instance_struct_size () {
81		return "sizeof (%s)".printf (get_ccode_name (class_reference));
82	}
83
84	public override string get_instance_init_func_name () {
85		return "%s_instance_init".printf (get_ccode_lower_case_name (class_reference, null));
86	}
87
88	public override string get_parent_type_name () {
89		return get_ccode_type_id (class_reference.base_class);
90	}
91
92	public override string get_type_flags () {
93		if (class_reference.is_abstract) {
94			return "G_TYPE_FLAG_ABSTRACT";
95		} else {
96			return "0";
97		}
98	}
99
100	public override SymbolAccessibility get_accessibility () {
101		return class_reference.access;
102	}
103
104	public override string? get_gtype_value_table_init_function_name () {
105		bool is_fundamental = !class_reference.is_compact && class_reference.base_class == null;
106		if ( is_fundamental )
107			return "%s_init".printf (get_ccode_lower_case_name (class_reference, "value_"));
108
109		return null;
110	}
111
112	public override string? get_gtype_value_table_free_function_name () {
113		bool is_fundamental = !class_reference.is_compact && class_reference.base_class == null;
114		if ( is_fundamental )
115			return "%s_free_value".printf (get_ccode_lower_case_name (class_reference, "value_"));
116
117		return null;
118	}
119
120	public override string? get_gtype_value_table_copy_function_name () {
121		bool is_fundamental = !class_reference.is_compact && class_reference.base_class == null;
122		if ( is_fundamental )
123			return "%s_copy_value".printf (get_ccode_lower_case_name (class_reference, "value_"));
124
125		return null;
126	}
127
128	public override string? get_gtype_value_table_peek_pointer_function_name () {
129		bool is_fundamental = !class_reference.is_compact && class_reference.base_class == null;
130		if ( is_fundamental )
131			return "%s_peek_pointer".printf (get_ccode_lower_case_name (class_reference, "value_"));
132
133		return null;
134	}
135
136	public override string? get_gtype_value_table_collect_value_function_name () {
137		bool is_fundamental = !class_reference.is_compact && class_reference.base_class == null;
138		if ( is_fundamental )
139			return "%s_collect_value".printf (get_ccode_lower_case_name (class_reference, "value_"));
140
141		return null;
142	}
143
144	public override string? get_gtype_value_table_lcopy_value_function_name () {
145		bool is_fundamental = !class_reference.is_compact && class_reference.base_class == null;
146		if ( is_fundamental )
147			return "%s_lcopy_value".printf (get_ccode_lower_case_name (class_reference, "value_"));
148
149		return null;
150	}
151
152	public override CCodeFragment get_type_interface_init_declaration () {
153		var frag = new CCodeFragment ();
154
155		foreach (DataType base_type in class_reference.get_base_types ()) {
156			if (!(base_type.type_symbol is Interface)) {
157				continue;
158			}
159
160			unowned Interface iface = (Interface) base_type.type_symbol;
161
162			var iface_info_name = "%s_info".printf (get_ccode_lower_case_name (iface, null));
163
164			var ctypedecl = new CCodeDeclaration ("const GInterfaceInfo");
165			ctypedecl.modifiers = CCodeModifiers.STATIC;
166			ctypedecl.add_declarator (new CCodeVariableDeclarator (iface_info_name, new CCodeConstant ("{ (GInterfaceInitFunc) %s_%s_interface_init, (GInterfaceFinalizeFunc) NULL, NULL}".printf (get_ccode_lower_case_name (class_reference), get_ccode_lower_case_name (iface)))));
167			frag.append (ctypedecl);
168		}
169
170		return frag;
171	}
172
173	public override void get_type_interface_init_statements (CodeContext context, CCodeBlock block, bool plugin) {
174		foreach (DataType base_type in class_reference.get_base_types ()) {
175			if (!(base_type.type_symbol is Interface)) {
176				continue;
177			}
178
179			unowned Interface iface = (Interface) base_type.type_symbol;
180
181			var iface_info_name = "%s_info".printf (get_ccode_lower_case_name (iface, null));
182			if (!plugin) {
183				var reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_add_interface_static"));
184				reg_call.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (class_reference, null))));
185				reg_call.add_argument (new CCodeIdentifier (get_ccode_type_id (iface)));
186				reg_call.add_argument (new CCodeIdentifier ("&%s".printf (iface_info_name)));
187				block.add_statement (new CCodeExpressionStatement (reg_call));
188			} else {
189				var reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_module_add_interface"));
190				reg_call.add_argument (new CCodeIdentifier ("module"));
191				reg_call.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (class_reference, null))));
192				reg_call.add_argument (new CCodeIdentifier (get_ccode_type_id (iface)));
193				reg_call.add_argument (new CCodeIdentifier ("&%s".printf (iface_info_name)));
194				block.add_statement (new CCodeExpressionStatement (reg_call));
195			}
196		}
197
198		((CCodeBaseModule) context.codegen).register_dbus_info (block, class_reference);
199	}
200}
201