1 /* valacodegeneratorclass.vala
3 * Copyright (C) 2006-2007 Jürg Billeter, Raffaele Sandrini
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 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
20 * Jürg Billeter <j@bitron.ch>
21 * Raffaele Sandrini <rasa@gmx.ch>
26 public class Vala
.CodeGenerator
{
27 public override void visit_class (Class
! cl
) {
28 current_symbol
= cl
.symbol
;
29 current_type_symbol
= cl
.symbol
;
36 instance_struct
= new
CCodeStruct ("_%s".printf (cl
.get_cname ()));
37 type_struct
= new
CCodeStruct ("_%sClass".printf (cl
.get_cname ()));
38 instance_priv_struct
= new
CCodeStruct ("_%sPrivate".printf (cl
.get_cname ()));
39 prop_enum
= new
CCodeEnum ();
40 prop_enum
.add_value ("%s_DUMMY_PROPERTY".printf (cl
.get_upper_case_cname (null)), null);
41 instance_init_fragment
= new
CCodeFragment ();
42 instance_dispose_fragment
= new
CCodeFragment ();
45 header_type_declaration
.append (new
CCodeNewline ());
46 var macro
= "(%s_get_type ())".printf (cl
.get_lower_case_cname (null));
47 header_type_declaration
.append (new
CCodeMacroReplacement (cl
.get_upper_case_cname ("TYPE_"), macro
));
49 macro
= "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (cl
.get_upper_case_cname ("TYPE_"), cl
.get_cname ());
50 header_type_declaration
.append (new
CCodeMacroReplacement ("%s(obj)".printf (cl
.get_upper_case_cname (null)), macro
));
52 macro
= "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %sClass))".printf (cl
.get_upper_case_cname ("TYPE_"), cl
.get_cname ());
53 header_type_declaration
.append (new
CCodeMacroReplacement ("%s_CLASS(klass)".printf (cl
.get_upper_case_cname (null)), macro
));
55 macro
= "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (cl
.get_upper_case_cname ("TYPE_"));
56 header_type_declaration
.append (new
CCodeMacroReplacement ("%s(obj)".printf (cl
.get_upper_case_cname ("IS_")), macro
));
58 macro
= "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (cl
.get_upper_case_cname ("TYPE_"));
59 header_type_declaration
.append (new
CCodeMacroReplacement ("%s_CLASS(klass)".printf (cl
.get_upper_case_cname ("IS_")), macro
));
61 macro
= "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %sClass))".printf (cl
.get_upper_case_cname ("TYPE_"), cl
.get_cname ());
62 header_type_declaration
.append (new
CCodeMacroReplacement ("%s_GET_CLASS(obj)".printf (cl
.get_upper_case_cname (null)), macro
));
63 header_type_declaration
.append (new
CCodeNewline ());
66 if (cl
.source_reference
.file
.cycle
== null) {
67 header_type_declaration
.append (new
CCodeTypeDefinition ("struct %s".printf (instance_struct
.name
), new
CCodeVariableDeclarator (cl
.get_cname ())));
68 header_type_declaration
.append (new
CCodeTypeDefinition ("struct %s".printf (type_struct
.name
), new
CCodeVariableDeclarator ("%sClass".printf (cl
.get_cname ()))));
70 header_type_declaration
.append (new
CCodeTypeDefinition ("struct %s".printf (instance_priv_struct
.name
), new
CCodeVariableDeclarator ("%sPrivate".printf (cl
.get_cname ()))));
72 instance_struct
.add_field (cl
.base_class
.get_cname (), "parent");
73 instance_struct
.add_field ("%sPrivate *".printf (cl
.get_cname ()), "priv");
74 type_struct
.add_field ("%sClass".printf (cl
.base_class
.get_cname ()), "parent");
76 if (cl
.source_reference
.comment
!= null) {
77 header_type_definition
.append (new
CCodeComment (cl
.source_reference
.comment
));
79 header_type_definition
.append (instance_struct
);
80 header_type_definition
.append (type_struct
);
81 /* only add the *Private struct if it is not empty, i.e. we actually have private data */
82 if (cl
.has_private_fields
) {
83 source_type_member_declaration
.append (instance_priv_struct
);
84 macro
= "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl
.get_upper_case_cname ("TYPE_"), cl
.get_cname ());
85 source_type_member_declaration
.append (new
CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl
.get_upper_case_cname (null)), macro
));
87 source_type_member_declaration
.append (prop_enum
);
89 cl
.accept_children (this
);
92 if (class_has_readable_properties (cl
)) {
93 add_get_property_function (cl
);
95 if (class_has_writable_properties (cl
)) {
96 add_set_property_function (cl
);
98 add_class_init_function (cl
);
100 foreach (TypeReference base_type
in cl
.get_base_types ()) {
101 if (base_type
.data_type is Interface
) {
102 add_interface_init_function (cl
, (Interface
) base_type
.data_type
);
106 add_instance_init_function (cl
);
107 if (memory_management
&& cl
.get_fields () != null) {
108 add_dispose_function (cl
);
111 var type_fun
= new
ClassRegisterFunction (cl
);
112 type_fun
.init_from_type (in_plugin
);
113 header_type_member_declaration
.append (type_fun
.get_declaration ());
114 source_type_member_definition
.append (type_fun
.get_definition ());
117 // FIXME resolve potential dependency issues, i.e. base types have to be registered before derived types
118 var register_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_register_type".printf (cl
.get_lower_case_cname (null))));
119 register_call
.add_argument (new
CCodeIdentifier (module_init_param_name
));
120 module_init_fragment
.append (new
CCodeExpressionStatement (register_call
));
124 current_type_symbol
= null;
125 current_class
= null;
126 instance_dispose_fragment
= null;
129 private void add_class_init_function (Class
! cl
) {
130 var class_init
= new
CCodeFunction ("%s_class_init".printf (cl
.get_lower_case_cname (null)), "void");
131 class_init
.add_parameter (new
CCodeFormalParameter ("klass", "%sClass *".printf (cl
.get_cname ())));
132 class_init
.modifiers
= CCodeModifiers
.STATIC
;
134 var init_block
= new
CCodeBlock ();
135 class_init
.block
= init_block
;
137 CCodeFunctionCall ccall
;
139 /* save pointer to parent class */
140 var parent_decl
= new
CCodeDeclaration ("gpointer");
141 var parent_var_decl
= new
CCodeVariableDeclarator ("%s_parent_class".printf (cl
.get_lower_case_cname (null)));
142 parent_var_decl
.initializer
= new
CCodeConstant ("NULL");
143 parent_decl
.add_declarator (parent_var_decl
);
144 parent_decl
.modifiers
= CCodeModifiers
.STATIC
;
145 source_type_member_declaration
.append (parent_decl
);
146 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_peek_parent"));
147 ccall
.add_argument (new
CCodeIdentifier ("klass"));
148 var parent_assignment
= new
CCodeAssignment (new
CCodeIdentifier ("%s_parent_class".printf (cl
.get_lower_case_cname (null))), ccall
);
149 init_block
.add_statement (new
CCodeExpressionStatement (parent_assignment
));
151 /* add struct for private fields */
152 if (cl
.has_private_fields
) {
153 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_add_private"));
154 ccall
.add_argument (new
CCodeIdentifier ("klass"));
155 ccall
.add_argument (new
CCodeConstant ("sizeof (%sPrivate)".printf (cl
.get_cname ())));
156 init_block
.add_statement (new
CCodeExpressionStatement (ccall
));
159 /* set property handlers */
160 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_OBJECT_CLASS"));
161 ccall
.add_argument (new
CCodeIdentifier ("klass"));
162 if (class_has_readable_properties (cl
)) {
163 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccall
, "get_property"), new
CCodeIdentifier ("%s_get_property".printf (cl
.get_lower_case_cname (null))))));
165 if (class_has_writable_properties (cl
)) {
166 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccall
, "set_property"), new
CCodeIdentifier ("%s_set_property".printf (cl
.get_lower_case_cname (null))))));
169 /* set constructor */
170 if (cl
.constructor
!= null) {
171 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_OBJECT_CLASS"));
172 ccast
.add_argument (new
CCodeIdentifier ("klass"));
173 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, "constructor"), new
CCodeIdentifier ("%s_constructor".printf (cl
.get_lower_case_cname (null))))));
176 /* set dispose function */
177 if (memory_management
&& cl
.get_fields () != null) {
178 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_OBJECT_CLASS"));
179 ccast
.add_argument (new
CCodeIdentifier ("klass"));
180 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, "dispose"), new
CCodeIdentifier ("%s_dispose".printf (cl
.get_lower_case_cname (null))))));
183 /* connect overridden methods */
184 var methods
= cl
.get_methods ();
185 foreach (Method m
in methods
) {
186 if (m
.base_method
== null) {
189 var base_type
= m
.base_method
.symbol
.parent_symbol
.node
;
191 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (((Class
) base_type
).get_upper_case_cname (null))));
192 ccast
.add_argument (new
CCodeIdentifier ("klass"));
193 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, m
.name
), new
CCodeIdentifier (m
.get_real_cname ()))));
196 /* create destroy_func properties for generic types */
197 foreach (TypeParameter type_param
in cl
.get_type_parameters ()) {
198 string func_name
= "%s_destroy_func".printf (type_param
.name
.down ());
199 var func_name_constant
= new
CCodeConstant ("\"%s-destroy-func\"".printf (type_param
.name
.down ()));
200 string enum_value
= "%s_%s".printf (cl
.get_lower_case_cname (null), func_name
).up ();
201 var cinst
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_class_install_property"));
202 cinst
.add_argument (ccall
);
203 cinst
.add_argument (new
CCodeConstant (enum_value
));
204 var cspec
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_param_spec_pointer"));
205 cspec
.add_argument (func_name_constant
);
206 cspec
.add_argument (new
CCodeConstant ("\"destroy func\""));
207 cspec
.add_argument (new
CCodeConstant ("\"destroy func\""));
208 cspec
.add_argument (new
CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY"));
209 cinst
.add_argument (cspec
);
210 init_block
.add_statement (new
CCodeExpressionStatement (cinst
));
211 prop_enum
.add_value (enum_value
, null);
213 instance_priv_struct
.add_field ("GDestroyNotify", func_name
);
216 /* create properties */
217 var props
= cl
.get_properties ();
218 foreach (Property prop
in props
) {
219 if (prop
.overrides
|| prop
.base_interface_property
!= null) {
220 var cinst
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_class_override_property"));
221 cinst
.add_argument (ccall
);
222 cinst
.add_argument (new
CCodeConstant (prop
.get_upper_case_cname ()));
223 cinst
.add_argument (prop
.get_canonical_cconstant ());
225 init_block
.add_statement (new
CCodeExpressionStatement (cinst
));
227 var cinst
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_class_install_property"));
228 cinst
.add_argument (ccall
);
229 cinst
.add_argument (new
CCodeConstant (prop
.get_upper_case_cname ()));
230 cinst
.add_argument (get_param_spec (prop
));
232 init_block
.add_statement (new
CCodeExpressionStatement (cinst
));
237 foreach (Signal sig
in cl
.get_signals ()) {
238 init_block
.add_statement (new
CCodeExpressionStatement (get_signal_creation (sig
, cl
)));
241 source_type_member_definition
.append (class_init
);
244 private void add_interface_init_function (Class
! cl
, Interface
! iface
) {
245 var iface_init
= new
CCodeFunction ("%s_%s_interface_init".printf (cl
.get_lower_case_cname (null), iface
.get_lower_case_cname (null)), "void");
246 iface_init
.add_parameter (new
CCodeFormalParameter ("iface", "%s *".printf (iface
.get_type_cname ())));
247 iface_init
.modifiers
= CCodeModifiers
.STATIC
;
249 var init_block
= new
CCodeBlock ();
250 iface_init
.block
= init_block
;
252 CCodeFunctionCall ccall
;
254 /* save pointer to parent vtable */
255 string parent_iface_var
= "%s_%s_parent_iface".printf (cl
.get_lower_case_cname (null), iface
.get_lower_case_cname (null));
256 var parent_decl
= new
CCodeDeclaration (iface
.get_type_cname () + "*");
257 var parent_var_decl
= new
CCodeVariableDeclarator (parent_iface_var
);
258 parent_var_decl
.initializer
= new
CCodeConstant ("NULL");
259 parent_decl
.add_declarator (parent_var_decl
);
260 parent_decl
.modifiers
= CCodeModifiers
.STATIC
;
261 source_type_member_declaration
.append (parent_decl
);
262 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_interface_peek_parent"));
263 ccall
.add_argument (new
CCodeIdentifier ("iface"));
264 var parent_assignment
= new
CCodeAssignment (new
CCodeIdentifier (parent_iface_var
), ccall
);
265 init_block
.add_statement (new
CCodeExpressionStatement (parent_assignment
));
267 var methods
= cl
.get_methods ();
268 foreach (Method m
in methods
) {
269 if (m
.base_interface_method
== null) {
273 var base_type
= m
.base_interface_method
.symbol
.parent_symbol
.node
;
274 if (base_type
!= iface
) {
278 var ciface
= new
CCodeIdentifier ("iface");
279 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, m
.name
), new
CCodeIdentifier (m
.get_real_cname ()))));
282 source_type_member_definition
.append (iface_init
);
285 private void add_instance_init_function (Class
! cl
) {
286 var instance_init
= new
CCodeFunction ("%s_init".printf (cl
.get_lower_case_cname (null)), "void");
287 instance_init
.add_parameter (new
CCodeFormalParameter ("self", "%s *".printf (cl
.get_cname ())));
288 instance_init
.modifiers
= CCodeModifiers
.STATIC
;
290 var init_block
= new
CCodeBlock ();
291 instance_init
.block
= init_block
;
293 if (cl
.has_private_fields
) {
294 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_PRIVATE".printf (cl
.get_upper_case_cname (null))));
295 ccall
.add_argument (new
CCodeIdentifier ("self"));
296 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "priv"), ccall
)));
299 init_block
.add_statement (instance_init_fragment
);
301 var init_sym
= cl
.symbol
.lookup ("init");
302 if (init_sym
!= null) {
303 var init_fun
= (Method
) init_sym
.node
;
304 init_block
.add_statement (init_fun
.body
.ccodenode
);
307 source_type_member_definition
.append (instance_init
);
310 private void add_dispose_function (Class
! cl
) {
311 function
= new
CCodeFunction ("%s_dispose".printf (cl
.get_lower_case_cname (null)), "void");
312 function
.modifiers
= CCodeModifiers
.STATIC
;
314 function
.add_parameter (new
CCodeFormalParameter ("obj", "GObject *"));
316 source_type_member_declaration
.append (function
.copy ());
319 var cblock
= new
CCodeBlock ();
321 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_upper_case_cname (null)));
322 ccall
.add_argument (new
CCodeIdentifier ("obj"));
324 var cdecl
= new
CCodeDeclaration ("%s *".printf (cl
.get_cname ()));
325 cdecl
.add_declarator (new CCodeVariableDeclarator
.with_initializer ("self", ccall
));
327 cblock
.add_statement (cdecl
);
329 cblock
.add_statement (instance_dispose_fragment
);
331 cdecl
= new
CCodeDeclaration ("%sClass *".printf (cl
.get_cname ()));
332 cdecl
.add_declarator (new
CCodeVariableDeclarator ("klass"));
333 cblock
.add_statement (cdecl
);
335 cdecl
= new
CCodeDeclaration ("GObjectClass *");
336 cdecl
.add_declarator (new
CCodeVariableDeclarator ("parent_class"));
337 cblock
.add_statement (cdecl
);
340 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_peek"));
341 ccall
.add_argument (new
CCodeIdentifier (cl
.get_upper_case_cname ("TYPE_")));
342 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (cl
.get_upper_case_cname (null))));
343 ccast
.add_argument (ccall
);
344 cblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("klass"), ccast
)));
346 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_peek_parent"));
347 ccall
.add_argument (new
CCodeIdentifier ("klass"));
348 ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_OBJECT_CLASS"));
349 ccast
.add_argument (ccall
);
350 cblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("parent_class"), ccast
)));
353 ccall
= new
CCodeFunctionCall (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("parent_class"), "dispose"));
354 ccall
.add_argument (new
CCodeIdentifier ("obj"));
355 cblock
.add_statement (new
CCodeExpressionStatement (ccall
));
358 function
.block
= cblock
;
360 source_type_member_definition
.append (function
);
363 private CCodeIdentifier
! get_value_setter_function (TypeReference
! type_reference
) {
364 if (type_reference
.data_type is Class
|| type_reference
.data_type is Interface
) {
365 return new
CCodeIdentifier ("g_value_set_object");
366 } else if (type_reference
.data_type
== string_type
.data_type
) {
367 return new
CCodeIdentifier ("g_value_set_string");
368 } else if (type_reference
.data_type
== int_type
.data_type
369 || type_reference
.data_type is Enum
) {
370 return new
CCodeIdentifier ("g_value_set_int");
371 } else if (type_reference
.data_type
== uint_type
.data_type
) {
372 return new
CCodeIdentifier ("g_value_set_uint");
373 } else if (type_reference
.data_type
== long_type
.data_type
) {
374 return new
CCodeIdentifier ("g_value_set_long");
375 } else if (type_reference
.data_type
== ulong_type
.data_type
) {
376 return new
CCodeIdentifier ("g_value_set_ulong");
377 } else if (type_reference
.data_type
== bool_type
.data_type
) {
378 return new
CCodeIdentifier ("g_value_set_boolean");
379 } else if (type_reference
.data_type
== float_type
.data_type
) {
380 return new
CCodeIdentifier ("g_value_set_float");
381 } else if (type_reference
.data_type
== double_type
.data_type
) {
382 return new
CCodeIdentifier ("g_value_set_double");
384 return new
CCodeIdentifier ("g_value_set_pointer");
388 private bool class_has_readable_properties (Class
! cl
) {
389 foreach (Property prop
in cl
.get_properties ()) {
390 if (prop
.get_accessor
!= null && !prop
.is_abstract
) {
397 private bool class_has_writable_properties (Class
! cl
) {
398 foreach (Property prop
in cl
.get_properties ()) {
399 if (prop
.set_accessor
!= null && !prop
.is_abstract
) {
406 private void add_get_property_function (Class
! cl
) {
407 var get_prop
= new
CCodeFunction ("%s_get_property".printf (cl
.get_lower_case_cname (null)), "void");
408 get_prop
.modifiers
= CCodeModifiers
.STATIC
;
409 get_prop
.add_parameter (new
CCodeFormalParameter ("object", "GObject *"));
410 get_prop
.add_parameter (new
CCodeFormalParameter ("property_id", "guint"));
411 get_prop
.add_parameter (new
CCodeFormalParameter ("value", "GValue *"));
412 get_prop
.add_parameter (new
CCodeFormalParameter ("pspec", "GParamSpec *"));
414 var block
= new
CCodeBlock ();
416 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_upper_case_cname (null)));
417 ccall
.add_argument (new
CCodeIdentifier ("object"));
418 var cdecl
= new
CCodeDeclaration ("%s *".printf (cl
.get_cname ()));
419 cdecl
.add_declarator (new CCodeVariableDeclarator
.with_initializer ("self", ccall
));
420 block
.add_statement (cdecl
);
422 var cswitch
= new
CCodeSwitchStatement (new
CCodeIdentifier ("property_id"));
423 var props
= cl
.get_properties ();
424 foreach (Property prop
in props
) {
425 if (prop
.get_accessor
== null || prop
.is_abstract
) {
429 bool is_virtual
= prop
.base_property
!= null || prop
.base_interface_property
!= null;
431 string prefix
= cl
.get_lower_case_cname (null);
436 var ccase
= new
CCodeCaseStatement (new
CCodeIdentifier (prop
.get_upper_case_cname ()));
437 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_get_%s".printf (prefix
, prop
.name
)));
438 ccall
.add_argument (new
CCodeIdentifier ("self"));
439 var csetcall
= new
CCodeFunctionCall ();
440 csetcall
.call
= get_value_setter_function (prop
.type_reference
);
441 csetcall
.add_argument (new
CCodeIdentifier ("value"));
442 csetcall
.add_argument (ccall
);
443 ccase
.add_statement (new
CCodeExpressionStatement (csetcall
));
444 ccase
.add_statement (new
CCodeBreakStatement ());
445 cswitch
.add_case (ccase
);
447 block
.add_statement (cswitch
);
449 get_prop
.block
= block
;
451 source_type_member_definition
.append (get_prop
);
454 private void add_set_property_function (Class
! cl
) {
455 var set_prop
= new
CCodeFunction ("%s_set_property".printf (cl
.get_lower_case_cname (null)), "void");
456 set_prop
.modifiers
= CCodeModifiers
.STATIC
;
457 set_prop
.add_parameter (new
CCodeFormalParameter ("object", "GObject *"));
458 set_prop
.add_parameter (new
CCodeFormalParameter ("property_id", "guint"));
459 set_prop
.add_parameter (new
CCodeFormalParameter ("value", "const GValue *"));
460 set_prop
.add_parameter (new
CCodeFormalParameter ("pspec", "GParamSpec *"));
462 var block
= new
CCodeBlock ();
464 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_upper_case_cname (null)));
465 ccall
.add_argument (new
CCodeIdentifier ("object"));
466 var cdecl
= new
CCodeDeclaration ("%s *".printf (cl
.get_cname ()));
467 cdecl
.add_declarator (new CCodeVariableDeclarator
.with_initializer ("self", ccall
));
468 block
.add_statement (cdecl
);
470 var cswitch
= new
CCodeSwitchStatement (new
CCodeIdentifier ("property_id"));
471 var props
= cl
.get_properties ();
472 foreach (Property prop
in props
) {
473 if (prop
.set_accessor
== null || prop
.is_abstract
) {
477 bool is_virtual
= prop
.base_property
!= null || prop
.base_interface_property
!= null;
479 string prefix
= cl
.get_lower_case_cname (null);
484 var ccase
= new
CCodeCaseStatement (new
CCodeIdentifier (prop
.get_upper_case_cname ()));
485 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_set_%s".printf (prefix
, prop
.name
)));
486 ccall
.add_argument (new
CCodeIdentifier ("self"));
487 var cgetcall
= new
CCodeFunctionCall ();
488 if (prop
.type_reference
.data_type is Class
|| prop
.type_reference
.data_type is Interface
) {
489 cgetcall
.call
= new
CCodeIdentifier ("g_value_get_object");
490 } else if (prop
.type_reference
.type_name
== "string") {
491 cgetcall
.call
= new
CCodeIdentifier ("g_value_get_string");
492 } else if (prop
.type_reference
.type_name
== "int" || prop
.type_reference
.data_type is Enum
) {
493 cgetcall
.call
= new
CCodeIdentifier ("g_value_get_int");
494 } else if (prop
.type_reference
.type_name
== "uint") {
495 cgetcall
.call
= new
CCodeIdentifier ("g_value_get_uint");
496 } else if (prop
.type_reference
.type_name
== "long") {
497 cgetcall
.call
= new
CCodeIdentifier ("g_value_get_long");
498 } else if (prop
.type_reference
.type_name
== "ulong") {
499 cgetcall
.call
= new
CCodeIdentifier ("g_value_get_ulong");
500 } else if (prop
.type_reference
.type_name
== "bool") {
501 cgetcall
.call
= new
CCodeIdentifier ("g_value_get_boolean");
502 } else if (prop
.type_reference
.type_name
== "float") {
503 cgetcall
.call
= new
CCodeIdentifier ("g_value_get_float");
504 } else if (prop
.type_reference
.type_name
== "double") {
505 cgetcall
.call
= new
CCodeIdentifier ("g_value_get_double");
507 cgetcall
.call
= new
CCodeIdentifier ("g_value_get_pointer");
509 cgetcall
.add_argument (new
CCodeIdentifier ("value"));
510 ccall
.add_argument (cgetcall
);
511 ccase
.add_statement (new
CCodeExpressionStatement (ccall
));
512 ccase
.add_statement (new
CCodeBreakStatement ());
513 cswitch
.add_case (ccase
);
515 block
.add_statement (cswitch
);
517 /* destroy func properties for generic types */
518 foreach (TypeParameter type_param
in cl
.get_type_parameters ()) {
519 string func_name
= "%s_destroy_func".printf (type_param
.name
.down ());
520 string enum_value
= "%s_%s".printf (cl
.get_lower_case_cname (null), func_name
).up ();
522 var ccase
= new
CCodeCaseStatement (new
CCodeIdentifier (enum_value
));
523 var cfield
= new CCodeMemberAccess
.pointer (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "priv"), func_name
);
524 var cgetcall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_get_pointer"));
525 cgetcall
.add_argument (new
CCodeIdentifier ("value"));
526 ccase
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (cfield
, cgetcall
)));
527 ccase
.add_statement (new
CCodeBreakStatement ());
528 cswitch
.add_case (ccase
);
531 set_prop
.block
= block
;
533 source_type_member_definition
.append (set_prop
);