Release 0.6.0
[vala-lang.git] / gobject / valatyperegisterfunction.vala
blob85dfcc01b03eff11c87e78162ccc8432076824aa
1 /* valatyperegisterfunction.vala
3 * Copyright (C) 2006-2008 Jürg Billeter
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.
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.
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
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 using GLib;
25 /**
26 * C function to register a type at runtime.
28 public abstract class Vala.TypeRegisterFunction {
29 private CCodeFragment declaration_fragment = new CCodeFragment ();
31 private CCodeFragment definition_fragment = new CCodeFragment ();
33 public CodeContext context { get; set; }
35 /**
36 * Constructs the C function from the specified type.
38 public void init_from_type (bool plugin = false) {
39 bool use_thread_safe = context.require_glib_version (2, 14);
41 bool fundamental = false;
42 Class cl = get_type_declaration () as Class;
43 if (cl != null && !cl.is_compact && cl.base_class == null) {
44 fundamental = true;
47 string type_id_name = "%s_type_id".printf (get_type_declaration ().get_lower_case_cname (null));
49 var type_block = new CCodeBlock ();
50 CCodeDeclaration cdecl;
51 if (use_thread_safe) {
52 cdecl = new CCodeDeclaration ("gsize");
53 cdecl.add_declarator (new CCodeVariableDeclarator (type_id_name + "__volatile", new CCodeConstant ("0")));
54 } else {
55 cdecl = new CCodeDeclaration ("GType");
56 cdecl.add_declarator (new CCodeVariableDeclarator (type_id_name, new CCodeConstant ("0")));
58 cdecl.modifiers = CCodeModifiers.STATIC;
59 if (use_thread_safe) {
60 cdecl.modifiers |= CCodeModifiers.VOLATILE;
62 if (!plugin) {
63 type_block.add_statement (cdecl);
64 } else {
65 definition_fragment.append (cdecl);
68 CCodeFunction fun;
69 if (!plugin) {
70 fun = new CCodeFunction ("%s_get_type".printf (get_type_declaration ().get_lower_case_cname (null)), "GType");
71 /* Function will not be prototyped anyway */
72 if (get_accessibility () == SymbolAccessibility.PRIVATE) {
73 fun.modifiers = CCodeModifiers.STATIC;
75 } else {
76 fun = new CCodeFunction ("%s_register_type".printf (get_type_declaration ().get_lower_case_cname (null)), "GType");
77 fun.add_parameter (new CCodeFormalParameter ("module", "GTypeModule *"));
79 var get_fun = new CCodeFunction ("%s_get_type".printf (get_type_declaration ().get_lower_case_cname (null)), "GType");
80 if (get_accessibility () == SymbolAccessibility.PRIVATE) {
81 fun.modifiers = CCodeModifiers.STATIC;
84 declaration_fragment.append (get_fun.copy ());
86 get_fun.block = new CCodeBlock ();
87 get_fun.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier (type_id_name)));
89 definition_fragment.append (get_fun);
92 string type_value_table_decl_name = null;
93 var type_init = new CCodeBlock ();
95 if (fundamental) {
96 var cgtypetabledecl = new CCodeDeclaration ("const GTypeValueTable");
97 cgtypetabledecl.modifiers = CCodeModifiers.STATIC;
99 cgtypetabledecl.add_declarator (new CCodeVariableDeclarator ( "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 ()))));
100 type_value_table_decl_name = "&g_define_type_value_table";
101 type_init.add_statement ( cgtypetabledecl );
103 else {
104 type_value_table_decl_name = "NULL";
108 if (get_type_declaration () is ObjectTypeSymbol) {
109 var ctypedecl = new CCodeDeclaration ("const GTypeInfo");
110 ctypedecl.modifiers = CCodeModifiers.STATIC;
111 ctypedecl.add_declarator (new CCodeVariableDeclarator ("g_define_type_info", new CCodeConstant ("{ sizeof (%s), (GBaseInitFunc) %s, (GBaseFinalizeFunc) %s, (GClassInitFunc) %s, (GClassFinalizeFunc) %s, NULL, %s, 0, (GInstanceInitFunc) %s, %s }".printf (get_type_struct_name (), get_base_init_func_name (), (plugin) ? get_base_finalize_func_name () : "NULL", get_class_init_func_name (), get_class_finalize_func_name (), get_instance_struct_size (), get_instance_init_func_name (), type_value_table_decl_name))));
112 type_init.add_statement (ctypedecl);
113 if (fundamental) {
114 var ctypefundamentaldecl = new CCodeDeclaration ("const GTypeFundamentalInfo");
115 ctypefundamentaldecl.modifiers = CCodeModifiers.STATIC;
116 ctypefundamentaldecl.add_declarator (new CCodeVariableDeclarator ("g_define_type_fundamental_info", new CCodeConstant ("{ (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }")));
117 type_init.add_statement (ctypefundamentaldecl);
121 type_init.add_statement (get_type_interface_init_declaration ());
123 if (cl != null && cl.has_class_private_fields) {
124 CCodeFunctionCall quark_reg_call;
126 if (plugin) {
127 quark_reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
128 } else {
129 quark_reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
132 quark_reg_call.add_argument (new CCodeConstant ("\"Vala%sClassPrivate\"".printf (get_type_declaration ().get_cname ())));
134 type_init.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_vala_%s_class_private_quark".printf (get_type_declaration ().get_lower_case_cname ())), quark_reg_call)));
137 CCodeFunctionCall reg_call;
138 if (get_type_declaration () is Struct) {
139 reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_boxed_type_register_static"));
140 } else if (fundamental) {
141 reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_register_fundamental"));
142 reg_call.add_argument (new CCodeFunctionCall (new CCodeIdentifier ("g_type_fundamental_next")));
143 } else if (!plugin) {
144 reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_register_static"));
145 reg_call.add_argument (new CCodeIdentifier (get_parent_type_name ()));
146 } else {
147 reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_module_register_type"));
148 reg_call.add_argument (new CCodeIdentifier ("module"));
149 reg_call.add_argument (new CCodeIdentifier (get_parent_type_name ()));
151 reg_call.add_argument (new CCodeConstant ("\"%s\"".printf (get_type_declaration ().get_cname ())));
152 if (get_type_declaration () is Struct) {
153 var st = (Struct) get_type_declaration ();
154 reg_call.add_argument (new CCodeCastExpression (new CCodeIdentifier (st.get_dup_function ()), "GBoxedCopyFunc"));
155 reg_call.add_argument (new CCodeCastExpression (new CCodeIdentifier (st.get_free_function ()), "GBoxedFreeFunc"));
156 } else {
157 reg_call.add_argument (new CCodeIdentifier ("&g_define_type_info"));
158 if (fundamental) {
159 reg_call.add_argument (new CCodeIdentifier ("&g_define_type_fundamental_info"));
161 reg_call.add_argument (new CCodeConstant (get_type_flags ()));
164 if (use_thread_safe && !plugin) {
165 var temp_decl = new CCodeDeclaration ("GType");
166 temp_decl.add_declarator (new CCodeVariableDeclarator (type_id_name, reg_call));
167 type_init.add_statement (temp_decl);
168 } else {
169 type_init.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier (type_id_name), reg_call)));
172 type_init.add_statement (get_type_interface_init_statements ());
174 if (!plugin) {
175 CCodeExpression condition; // the condition that guards the type initialisation
176 if (use_thread_safe) {
177 var enter = new CCodeFunctionCall (new CCodeIdentifier ("g_once_init_enter"));
178 enter.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (type_id_name + "__volatile")));
179 condition = enter;
181 var leave = new CCodeFunctionCall (new CCodeIdentifier ("g_once_init_leave"));
182 leave.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (type_id_name + "__volatile")));
183 leave.add_argument (new CCodeIdentifier (type_id_name));
184 type_init.add_statement (new CCodeExpressionStatement (leave));
185 } else {
186 var id = new CCodeIdentifier (type_id_name);
187 var zero = new CCodeConstant ("0");
188 condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, id, zero);
191 var cif = new CCodeIfStatement (condition, type_init);
192 type_block.add_statement (cif);
193 } else {
194 type_block = type_init;
197 if (use_thread_safe) {
198 type_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier (type_id_name + "__volatile")));
199 } else {
200 type_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier (type_id_name)));
203 declaration_fragment.append (fun.copy ());
205 fun.block = type_block;
207 definition_fragment.append (fun);
211 * Returns the data type to be registered.
213 * @return type to be registered
215 public abstract TypeSymbol get_type_declaration ();
218 * Returns the name of the type struct in C code.
220 * @return C struct name
222 public virtual string get_type_struct_name () {
223 assert_not_reached ();
226 * Returns the name of the base_init function in C code.
228 * @return C function name
230 public virtual string get_base_init_func_name () {
231 assert_not_reached ();
235 * Returns the name of the class_finalize function in C code.
237 * @return C function name
239 public virtual string get_class_finalize_func_name () {
240 assert_not_reached ();
244 * Returns the name of the base_finalize function in C code.
246 * @return C function name
248 public virtual string get_base_finalize_func_name () {
249 assert_not_reached ();
253 * Returns the name of the class_init function in C code.
255 * @return C function name
257 public virtual string get_class_init_func_name () {
258 assert_not_reached ();
262 * Returns the size of the instance struct in C code.
264 * @return C instance struct size
266 public virtual string get_instance_struct_size () {
267 assert_not_reached ();
271 * Returns the name of the instance_init function in C code.
273 * @return C function name
275 public virtual string get_instance_init_func_name () {
276 assert_not_reached ();
280 * Returns the name of the parent type in C code.
282 * @return C function name
284 public virtual string get_parent_type_name () {
285 assert_not_reached ();
291 * Returns the C-name of the new generated GTypeValueTable init function or null when not available.
293 * @return C function name
295 public virtual string? get_gtype_value_table_init_function_name () {
296 return null;
300 * Returns the C-name of the new generated GTypeValueTable peek pointer function or null when not available.
302 * @return C function name
304 public virtual string? get_gtype_value_table_peek_pointer_function_name () {
305 return null;
309 * Returns the C-name of the new generated GTypeValueTable free function or null when not available.
311 * @return C function name
313 public virtual string? get_gtype_value_table_free_function_name () {
314 return null;
318 * Returns the C-name of the new generated GTypeValueTable copy function or null when not available.
320 * @return C function name
322 public virtual string? get_gtype_value_table_copy_function_name () {
323 return null;
327 * Returns the C-name of the new generated GTypeValueTable lcopy function or null when not available.
329 * @return C function name
331 public virtual string? get_gtype_value_table_lcopy_value_function_name () {
332 return null;
336 * Returns the C-name of the new generated GTypeValueTable collect value function or null when not available.
338 * @return C function name
340 public virtual string? get_gtype_value_table_collect_value_function_name () {
341 return null;
345 * Returns the set of type flags to be applied when registering.
347 * @return type flags
349 public virtual string get_type_flags () {
350 return "0";
354 * Returns additional C declarations to setup interfaces.
356 * @return C declarations
358 public virtual CCodeFragment get_type_interface_init_declaration () {
359 return new CCodeFragment ();
363 * Returns additional C initialization statements to setup interfaces.
365 * @return C statements
367 public abstract CCodeFragment get_type_interface_init_statements ();
370 * Returns the declaration for this type register function in C code.
372 * @return C function declaration fragment
374 public CCodeFragment get_declaration () {
375 return declaration_fragment;
379 * Returns the definition for this type register function in C code.
381 * @return C function definition fragment
383 public CCodeFragment get_definition () {
384 return definition_fragment;
388 * Returns the accessibility for this type.
390 public abstract SymbolAccessibility get_accessibility ();