valatyperegisterfunction.vala 6.71 KB
Newer Older
1
2
/* valatyperegisterfunction.vala
 *
3
 * Copyright (C) 2006-2007  Jürg Billeter
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 *
 * 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 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:
 * 	Jürg Billeter <j@bitron.ch>
 */

using GLib;

25
26
27
/**
 * C function to register a type at runtime.
 */
28
public abstract class Vala.TypeRegisterFunction : Object {
29
30
31
32
	private CCodeFragment declaration_fragment = new CCodeFragment ();

	private CCodeFragment definition_fragment = new CCodeFragment ();

33
34
35
	/**
	 * Constructs the C function from the specified type.
	 */
36
37
	public void init_from_type (bool plugin = false) {
		string type_id_name = "%s_type_id".printf (get_type_declaration ().get_lower_case_cname (null));
38

39
		var type_block = new CCodeBlock ();
40
		var cdecl = new CCodeDeclaration ("GType");
41
		cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (type_id_name, new CCodeConstant ("0")));
42
		cdecl.modifiers = CCodeModifiers.STATIC;
43
44
45
46
47
48
49
50
51
		if (!plugin) {
			type_block.add_statement (cdecl);
		} else {
			definition_fragment.append (cdecl);
		}

		CCodeFunction fun;
		if (!plugin) {
			fun = new CCodeFunction ("%s_get_type".printf (get_type_declaration ().get_lower_case_cname (null)), "GType");
52
			/* Function will not be prototyped anyway */
53
			if (get_accessibility () == SymbolAccessibility.PRIVATE) {
54
55
				fun.modifiers = CCodeModifiers.STATIC;
			}
56
57
58
59
60
		} else {
			fun = new CCodeFunction ("%s_register_type".printf (get_type_declaration ().get_lower_case_cname (null)), "GType");
			fun.add_parameter (new CCodeFormalParameter ("module", "GTypeModule *"));

			var get_fun = new CCodeFunction ("%s_get_type".printf (get_type_declaration ().get_lower_case_cname (null)), "GType");
61
			if (get_accessibility () == SymbolAccessibility.PRIVATE) {
62
63
				fun.modifiers = CCodeModifiers.STATIC;
			}
64
65
66
67
68
69
70
71
72

			declaration_fragment.append (get_fun.copy ());

			get_fun.block = new CCodeBlock ();
			get_fun.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier (type_id_name)));

			definition_fragment.append (get_fun);
		}

73
		var type_init = new CCodeBlock ();
74
		var ctypedecl = new CCodeDeclaration ("const GTypeInfo");
75
		ctypedecl.modifiers = CCodeModifiers.STATIC;
76
		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 ()))));
77
		type_init.add_statement (ctypedecl);
78
79
80

		type_init.add_statement (get_type_interface_init_declaration ());

81
82
83
84
85
86
87
		CCodeFunctionCall reg_call;
		if (!plugin) {
			reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_register_static"));
		} else {
			reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_module_register_type"));
			reg_call.add_argument (new CCodeIdentifier ("module"));
		}
88
89
90
91
		reg_call.add_argument (new CCodeIdentifier (get_parent_type_name ()));
		reg_call.add_argument (new CCodeConstant ("\"%s\"".printf (get_type_declaration ().get_cname ())));
		reg_call.add_argument (new CCodeIdentifier ("&g_define_type_info"));
		reg_call.add_argument (new CCodeConstant (get_type_flags ()));
92
		type_init.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier (type_id_name), reg_call)));
93
		
94
95
		type_init.add_statement (get_type_interface_init_statements ());

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
		if (!plugin) {
			var cond = new CCodeFunctionCall (new CCodeIdentifier ("G_UNLIKELY"));
			cond.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier (type_id_name), new CCodeConstant ("0")));
			var cif = new CCodeIfStatement (cond, type_init);
			type_block.add_statement (cif);
		} else {
			type_block = type_init;
		}

		type_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier (type_id_name)));

		declaration_fragment.append (fun.copy ());

		fun.block = type_block;

		definition_fragment.append (fun);
112
113
114
115
116
117
118
119
120
121
122
123
124
125
	}
	
	/**
	 * Returns the data type to be registered.
	 *
	 * @return type to be registered
	 */
	public abstract DataType! get_type_declaration ();

	/**
	 * Returns the name of the type struct in C code.
	 *
	 * @return C struct name
	 */
126
	public abstract string! get_type_struct_name ();
127

128
129
130
131
132
	/**
	 * Returns the name of the base_init function in C code.
	 *
	 * @return C function name
	 */
133
	public abstract string! get_base_init_func_name ();
134

135
136
137
138
139
	/**
	 * Returns the name of the class_init function in C code.
	 *
	 * @return C function name
	 */
140
	public abstract string! get_class_init_func_name ();
141
142
143
144
145
146

	/**
	 * Returns the size of the instance struct in C code.
	 *
	 * @return C instance struct size
	 */
147
	public abstract string! get_instance_struct_size ();
148
149
150
151
152
153

	/**
	 * Returns the name of the instance_init function in C code.
	 *
	 * @return C function name
	 */
154
	public abstract string! get_instance_init_func_name ();
155
156
157
158
159
160

	/**
	 * Returns the name of the parent type in C code.
	 *
	 * @return C parent type name
	 */
161
	public abstract string! get_parent_type_name ();
162

163
164
165
166
167
168
169
170
171
	/**
	 * Returns the set of type flags to be applied when registering.
	 *
	 * @return type flags
	 */
	public virtual string get_type_flags () {
		return "0";
	}

172
173
174
175
176
	/**
	 * Returns additional C declarations to setup interfaces.
	 *
	 * @return C declarations
	 */
177
	public virtual CCodeFragment! get_type_interface_init_declaration () {
178
179
180
		return new CCodeFragment ();
	}

181
182
183
184
185
	/**
	 * Returns additional C initialization statements to setup interfaces.
	 *
	 * @return C statements
	 */
186
	public abstract CCodeFragment! get_type_interface_init_statements ();
187
188
189
190
	
	/**
	 * Returns the declaration for this type register function in C code.
	 *
191
192
193
194
195
196
197
198
199
200
	 * @return C function declaration fragment
	 */
	public CCodeFragment! get_declaration () {
		return declaration_fragment;
	}
	
	/**
	 * Returns the definition for this type register function in C code.
	 *
	 * @return C function definition fragment
201
	 */
202
203
	public CCodeFragment! get_definition () {
		return definition_fragment;
204
	}
205
206
207
208

	/**
	 * Returns the accessibility for this type.
	 */
209
	public abstract SymbolAccessibility get_accessibility ();
210
}