Release 0.41.92
[vala-gnome.git] / codegen / valaccodestructmodule.vala
blobd9237e656f49f4c30bfed59b72b2eaec19f8363e
1 /* valaccodestructmodule.vala
3 * Copyright (C) 2006-2009 Jürg Billeter
4 * Copyright (C) 2006-2008 Raffaele Sandrini
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Author:
21 * Jürg Billeter <j@bitron.ch>
22 * Raffaele Sandrini <raffaele@sandrini.ch>
25 using GLib;
27 public abstract class Vala.CCodeStructModule : CCodeBaseModule {
28 public override void generate_struct_declaration (Struct st, CCodeFile decl_space) {
29 if (add_symbol_declaration (decl_space, st, get_ccode_name (st))) {
30 return;
33 if (st.is_boolean_type () || st.is_integer_type () || st.is_floating_type ()) {
34 if (st.base_struct != null) {
35 generate_struct_declaration (st.base_struct, decl_space);
36 decl_space.add_type_declaration (new CCodeTypeDefinition (get_ccode_name (st.base_struct), new CCodeVariableDeclarator (get_ccode_name (st))));
37 } else {
38 string typename = null;
39 if (st.is_boolean_type ()) {
40 // typedef for boolean types
41 decl_space.add_include ("stdbool.h");
42 typename = "bool";
43 } else if (st.is_integer_type ()) {
44 // typedef for integral types
45 decl_space.add_include ("stdint.h");
46 typename = "%sint%d_t".printf (st.signed ? "" : "u", st.width);
47 } else if (st.is_floating_type ()) {
48 // typedef for floating types
49 typename = (st.width == 64 ? "double" : "float");
51 decl_space.add_type_declaration (new CCodeTypeDefinition (typename, new CCodeVariableDeclarator (get_ccode_name (st))));
53 return;
56 if (context.profile == Profile.GOBJECT) {
57 if (get_ccode_has_type_id (st)) {
58 decl_space.add_include ("glib-object.h");
59 decl_space.add_type_declaration (new CCodeNewline ());
60 var macro = "(%s_get_type ())".printf (get_ccode_lower_case_name (st, null));
61 decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (st), macro));
63 var type_fun = new StructRegisterFunction (st);
64 type_fun.init_from_type (context, false, true);
65 decl_space.add_type_member_declaration (type_fun.get_declaration ());
69 var instance_struct = new CCodeStruct ("_%s".printf (get_ccode_name (st)));
70 instance_struct.modifiers |= (st.version.deprecated ? CCodeModifiers.DEPRECATED : 0);
72 foreach (Field f in st.get_fields ()) {
73 if (f.binding == MemberBinding.INSTANCE) {
74 generate_type_declaration (f.variable_type, decl_space);
75 CCodeModifiers modifiers = (f.is_volatile ? CCodeModifiers.VOLATILE : 0) | (f.version.deprecated ? CCodeModifiers.DEPRECATED : 0);
76 instance_struct.add_field (get_ccode_name (f.variable_type), get_ccode_name (f), modifiers, get_ccode_declarator_suffix (f.variable_type));
77 if (f.variable_type is ArrayType && get_ccode_array_length (f)) {
78 // create fields to store array dimensions
79 var array_type = (ArrayType) f.variable_type;
81 if (!array_type.fixed_length) {
82 var len_type = int_type.copy ();
84 for (int dim = 1; dim <= array_type.rank; dim++) {
85 string length_cname;
86 if (get_ccode_array_length_name (f) != null) {
87 length_cname = get_ccode_array_length_name (f);
88 } else {
89 length_cname = get_array_length_cname (get_ccode_name (f), dim);
91 instance_struct.add_field (get_ccode_name (len_type), length_cname);
94 if (array_type.rank == 1 && f.is_internal_symbol ()) {
95 instance_struct.add_field (get_ccode_name (len_type), get_array_size_cname (get_ccode_name (f)));
98 } else if (f.variable_type is DelegateType && get_ccode_delegate_target (f)) {
99 var delegate_type = (DelegateType) f.variable_type;
100 if (delegate_type.delegate_symbol.has_target) {
101 // create field to store delegate target
102 instance_struct.add_field ("gpointer", get_ccode_delegate_target_name (f));
103 if (delegate_type.is_disposable ()) {
104 instance_struct.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_ccode_name (f)));
111 if (st.base_struct == null) {
112 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (st)), new CCodeVariableDeclarator (get_ccode_name (st))));
114 decl_space.add_type_definition (instance_struct);
115 } else {
116 decl_space.add_type_declaration (new CCodeTypeDefinition (get_ccode_name (st.base_struct), new CCodeVariableDeclarator (get_ccode_name (st))));
119 var function = new CCodeFunction (get_ccode_dup_function (st), get_ccode_name (st) + "*");
120 if (st.is_private_symbol ()) {
121 function.modifiers = CCodeModifiers.STATIC;
122 } else if (context.hide_internal && st.is_internal_symbol ()) {
123 function.modifiers = CCodeModifiers.INTERNAL;
125 function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*"));
126 decl_space.add_function_declaration (function);
128 function = new CCodeFunction (get_ccode_free_function (st), "void");
129 if (st.is_private_symbol ()) {
130 function.modifiers = CCodeModifiers.STATIC;
131 } else if (context.hide_internal && st.is_internal_symbol ()) {
132 function.modifiers = CCodeModifiers.INTERNAL;
134 function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*"));
135 decl_space.add_function_declaration (function);
137 if (st.is_disposable ()) {
138 function = new CCodeFunction (get_ccode_copy_function (st), "void");
139 if (st.is_private_symbol ()) {
140 function.modifiers = CCodeModifiers.STATIC;
141 } else if (context.hide_internal && st.is_internal_symbol ()) {
142 function.modifiers = CCodeModifiers.INTERNAL;
144 function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*"));
145 function.add_parameter (new CCodeParameter ("dest", get_ccode_name (st) + "*"));
146 decl_space.add_function_declaration (function);
148 function = new CCodeFunction (get_ccode_destroy_function (st), "void");
149 if (st.is_private_symbol ()) {
150 function.modifiers = CCodeModifiers.STATIC;
151 } else if (context.hide_internal && st.is_internal_symbol ()) {
152 function.modifiers = CCodeModifiers.INTERNAL;
154 function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*"));
155 decl_space.add_function_declaration (function);
159 public override void visit_struct (Struct st) {
160 push_context (new EmitContext (st));
161 push_line (st.source_reference);
163 if (get_ccode_has_type_id (st) && get_ccode_name (st).length < 3) {
164 st.error = true;
165 Report.error (st.source_reference, "Name `%s' is too short for struct using GType".printf (get_ccode_name (st)));
166 return;
169 var old_instance_finalize_context = instance_finalize_context;
170 instance_finalize_context = new EmitContext ();
172 generate_struct_declaration (st, cfile);
174 if (!st.is_internal_symbol ()) {
175 generate_struct_declaration (st, header_file);
177 if (!st.is_private_symbol ()) {
178 generate_struct_declaration (st, internal_header_file);
181 if (!st.is_boolean_type () && !st.is_integer_type () && !st.is_floating_type ()) {
182 if (st.is_disposable ()) {
183 begin_struct_destroy_function (st);
187 st.accept_children (this);
189 if (!st.is_boolean_type () && !st.is_integer_type () && !st.is_floating_type ()) {
190 if (st.is_disposable ()) {
191 add_struct_copy_function (st);
192 add_struct_destroy_function (st);
195 add_struct_dup_function (st);
196 add_struct_free_function (st);
199 instance_finalize_context = old_instance_finalize_context;
201 pop_line ();
202 pop_context ();
205 void add_struct_dup_function (Struct st) {
206 var function = new CCodeFunction (get_ccode_dup_function (st), get_ccode_name (st) + "*");
207 if (st.access == SymbolAccessibility.PRIVATE) {
208 function.modifiers = CCodeModifiers.STATIC;
211 function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*"));
213 push_function (function);
215 ccode.add_declaration (get_ccode_name (st) + "*", new CCodeVariableDeclarator ("dup"));
217 if (context.profile == Profile.GOBJECT) {
218 var creation_call = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
219 creation_call.add_argument (new CCodeConstant (get_ccode_name (st)));
220 creation_call.add_argument (new CCodeConstant ("1"));
221 ccode.add_assignment (new CCodeIdentifier ("dup"), creation_call);
222 } else if (context.profile == Profile.POSIX) {
223 var creation_call = new CCodeFunctionCall (new CCodeIdentifier ("calloc"));
224 creation_call.add_argument (new CCodeConstant ("1"));
225 creation_call.add_argument (new CCodeIdentifier ("sizeof (%s*)".printf (get_ccode_name (st))));
226 ccode.add_assignment (new CCodeIdentifier ("dup"), creation_call);
229 if (st.is_disposable ()) {
230 var copy_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_copy_function (st)));
231 copy_call.add_argument (new CCodeIdentifier ("self"));
232 copy_call.add_argument (new CCodeIdentifier ("dup"));
233 ccode.add_expression (copy_call);
234 } else {
235 cfile.add_include ("string.h");
237 var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
238 sizeof_call.add_argument (new CCodeConstant (get_ccode_name (st)));
240 var copy_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
241 copy_call.add_argument (new CCodeIdentifier ("dup"));
242 copy_call.add_argument (new CCodeIdentifier ("self"));
243 copy_call.add_argument (sizeof_call);
244 ccode.add_expression (copy_call);
247 ccode.add_return (new CCodeIdentifier ("dup"));
249 pop_function ();
251 cfile.add_function (function);
254 void add_struct_free_function (Struct st) {
255 var function = new CCodeFunction (get_ccode_free_function (st), "void");
256 if (st.is_private_symbol ()) {
257 function.modifiers = CCodeModifiers.STATIC;
258 } else if (context.hide_internal && st.is_internal_symbol ()) {
259 function.modifiers = CCodeModifiers.INTERNAL;
262 function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*"));
264 push_function (function);
266 if (st.is_disposable ()) {
267 var destroy_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_destroy_function (st)));
268 destroy_call.add_argument (new CCodeIdentifier ("self"));
269 ccode.add_expression (destroy_call);
272 if (context.profile == Profile.GOBJECT) {
273 var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
274 free_call.add_argument (new CCodeIdentifier ("self"));
275 ccode.add_expression (free_call);
276 } else if (context.profile == Profile.POSIX) {
277 var free_call = new CCodeFunctionCall (new CCodeIdentifier ("free"));
278 free_call.add_argument (new CCodeIdentifier ("self"));
279 ccode.add_expression (free_call);
282 pop_function ();
284 cfile.add_function (function);
287 void add_struct_copy_function (Struct st) {
288 var function = new CCodeFunction (get_ccode_copy_function (st), "void");
289 if (st.is_private_symbol ()) {
290 function.modifiers = CCodeModifiers.STATIC;
291 } else if (context.hide_internal && st.is_internal_symbol ()) {
292 function.modifiers = CCodeModifiers.INTERNAL;
295 function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*"));
296 function.add_parameter (new CCodeParameter ("dest", get_ccode_name (st) + "*"));
298 push_function (function);
300 var dest_struct = new GLibValue (get_data_type_for_symbol (st), new CCodeIdentifier ("(*dest)"), true);
301 foreach (var f in st.get_fields ()) {
302 if (f.binding == MemberBinding.INSTANCE) {
303 var value = load_field (f, load_this_parameter ((TypeSymbol) st));
304 if (get_ccode_delegate_target (f) && requires_copy (f.variable_type)) {
305 value = copy_value (value, f);
306 if (value == null) {
307 // error case, continue to avoid critical
308 continue;
311 store_field (f, dest_struct, value);
315 pop_function ();
317 cfile.add_function (function);
320 void begin_struct_destroy_function (Struct st) {
321 push_context (instance_finalize_context);
323 var function = new CCodeFunction (get_ccode_destroy_function (st), "void");
324 if (st.is_private_symbol ()) {
325 function.modifiers = CCodeModifiers.STATIC;
326 } else if (context.hide_internal && st.is_internal_symbol ()) {
327 function.modifiers = CCodeModifiers.INTERNAL;
330 function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*"));
332 push_function (function);
334 pop_context ();
337 void add_struct_destroy_function (Struct st) {
338 cfile.add_function (instance_finalize_context.ccode);