LCOV - code coverage report
Current view: top level - codegen - valaccodestructmodule.vala (source / functions) Coverage Total Hit
Test: vala 0.57.0.298-a8cae1 Lines: 93.3 % 223 208
Test Date: 2024-04-25 11:34:36 Functions: - 0 0

            Line data    Source code
       1              : /* valaccodestructmodule.vala
       2              :  *
       3              :  * Copyright (C) 2006-2009  Jürg Billeter
       4              :  * Copyright (C) 2006-2008  Raffaele Sandrini
       5              :  *
       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.
      10              : 
      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.
      15              : 
      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
      19              :  *
      20              :  * Author:
      21              :  *      Jürg Billeter <j@bitron.ch>
      22              :  *      Raffaele Sandrini <raffaele@sandrini.ch>
      23              :  */
      24              : 
      25              : using GLib;
      26              : 
      27         2930 : public abstract class Vala.CCodeStructModule : CCodeBaseModule {
      28        37247 :         public override void generate_struct_declaration (Struct st, CCodeFile decl_space) {
      29        36904 :                 if (add_symbol_declaration (decl_space, st, get_ccode_name (st))) {
      30              :                         return;
      31              :                 }
      32              : 
      33          408 :                 if (st.base_struct != null) {
      34           58 :                         generate_struct_declaration (st.base_struct, decl_space);
      35          350 :                 } else if (!st.external_package) {
      36              :                         // custom simple type structs cannot have a type id which depends on head-allocation
      37          350 :                         if (st.has_attribute ("SimpleType") && !st.has_attribute_argument ("CCode", "type_id")) {
      38           31 :                                 st.set_attribute_bool ("CCode", "has_type_id", false);
      39              :                         }
      40              :                 }
      41              : 
      42          408 :                 if (st.is_boolean_type () || st.is_integer_type () || st.is_floating_type ()) {
      43              :                         string typename;
      44              :                         // See GTypeModule.visit_struct()
      45           51 :                         if (st.base_struct != null) {
      46           32 :                                 typename = get_ccode_name (st.base_struct);
      47           19 :                         } else if (st.is_boolean_type ()) {
      48              :                                 // typedef for boolean types
      49            5 :                                 decl_space.add_include ("stdbool.h");
      50            5 :                                 typename = "bool";
      51           14 :                         } else if (st.is_integer_type ()) {
      52              :                                 // typedef for integral types
      53           10 :                                 decl_space.add_include ("stdint.h");
      54           10 :                                 typename = "%sint%d_t".printf (st.signed ? "" : "u", st.width);
      55            4 :                         } else if (st.is_floating_type ()) {
      56              :                                 // typedef for floating types
      57            8 :                                 typename = (st.width == 64 ? "double" : "float");
      58              :                         } else {
      59            0 :                                 assert_not_reached ();
      60              :                         }
      61           51 :                         decl_space.add_type_declaration (new CCodeTypeDefinition (typename, new CCodeVariableDeclarator (get_ccode_name (st))));
      62           51 :                         return;
      63              :                 }
      64              : 
      65          357 :                 if (context.profile == Profile.GOBJECT) {
      66          649 :                         if (get_ccode_has_type_id (st)) {
      67          303 :                                 decl_space.add_include ("glib-object.h");
      68          303 :                                 decl_space.add_type_declaration (new CCodeNewline ());
      69          303 :                                 var macro = "(%s_get_type ())".printf (get_ccode_lower_case_name (st, null));
      70          303 :                                 decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (st), macro));
      71              : 
      72          303 :                                 var type_fun = new StructRegisterFunction (st);
      73          303 :                                 type_fun.init_from_type (context, false, true);
      74          303 :                                 decl_space.add_type_member_declaration (type_fun.get_declaration ());
      75              : 
      76          303 :                                 requires_vala_extern = true;
      77              :                         }
      78              :                 }
      79              : 
      80          357 :                 if (st.base_struct == null) {
      81          331 :                         decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (st)), new CCodeVariableDeclarator (get_ccode_name (st))));
      82              :                 } else {
      83           26 :                         decl_space.add_type_declaration (new CCodeTypeDefinition (get_ccode_name (st.base_struct), new CCodeVariableDeclarator (get_ccode_name (st))));
      84              :                 }
      85              : 
      86          357 :                 var instance_struct = new CCodeStruct ("_%s".printf (get_ccode_name (st)));
      87              : 
      88          357 :                 if (st.version.deprecated) {
      89            4 :                         if (context.profile == Profile.GOBJECT) {
      90            4 :                                 decl_space.add_include ("glib.h");
      91              :                         }
      92            4 :                         instance_struct.modifiers |= CCodeModifiers.DEPRECATED;
      93              :                 }
      94              : 
      95         1325 :                 foreach (Field f in st.get_fields ()) {
      96          484 :                         if (f.binding == MemberBinding.INSTANCE)  {
      97          472 :                                 append_field (instance_struct, f, decl_space);
      98              :                         }
      99              :                 }
     100              : 
     101          357 :                 if (st.base_struct == null) {
     102          331 :                         decl_space.add_type_definition (instance_struct);
     103              :                 }
     104              : 
     105          357 :                 if (st.is_simple_type ()) {
     106           14 :                         return;
     107              :                 }
     108              : 
     109          343 :                 var function = new CCodeFunction (get_ccode_dup_function (st), get_ccode_name (st) + "*");
     110          343 :                 if (st.is_private_symbol ()) {
     111            1 :                         function.modifiers = CCodeModifiers.STATIC;
     112          342 :                 } else if (context.hide_internal && st.is_internal_symbol ()) {
     113            0 :                         function.modifiers = CCodeModifiers.INTERNAL;
     114              :                 } else {
     115          342 :                         function.modifiers |= CCodeModifiers.EXTERN;
     116          342 :                         requires_vala_extern = true;
     117              :                 }
     118          343 :                 function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*"));
     119          343 :                 decl_space.add_function_declaration (function);
     120              : 
     121          343 :                 function = new CCodeFunction (get_ccode_free_function (st), "void");
     122          343 :                 if (st.is_private_symbol ()) {
     123            1 :                         function.modifiers = CCodeModifiers.STATIC;
     124          342 :                 } else if (context.hide_internal && st.is_internal_symbol ()) {
     125            0 :                         function.modifiers = CCodeModifiers.INTERNAL;
     126              :                 } else {
     127          342 :                         function.modifiers = CCodeModifiers.EXTERN;
     128          342 :                         requires_vala_extern = true;
     129              :                 }
     130          343 :                 function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*"));
     131          343 :                 decl_space.add_function_declaration (function);
     132              : 
     133          343 :                 if (st.is_disposable ()) {
     134          104 :                         function = new CCodeFunction (get_ccode_copy_function (st), "void");
     135          104 :                         if (st.is_private_symbol ()) {
     136            0 :                                 function.modifiers = CCodeModifiers.STATIC;
     137          104 :                         } else if (context.hide_internal && st.is_internal_symbol ()) {
     138            0 :                                 function.modifiers = CCodeModifiers.INTERNAL;
     139              :                         } else {
     140          104 :                                 function.modifiers = CCodeModifiers.EXTERN;
     141          104 :                                 requires_vala_extern = true;
     142              :                         }
     143          104 :                         function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*"));
     144          104 :                         function.add_parameter (new CCodeParameter ("dest", get_ccode_name (st) + "*"));
     145          104 :                         decl_space.add_function_declaration (function);
     146              : 
     147          104 :                         function = new CCodeFunction (get_ccode_destroy_function (st), "void");
     148          104 :                         if (st.is_private_symbol ()) {
     149            0 :                                 function.modifiers = CCodeModifiers.STATIC;
     150          104 :                         } else if (context.hide_internal && st.is_internal_symbol ()) {
     151            0 :                                 function.modifiers = CCodeModifiers.INTERNAL;
     152              :                         } else {
     153          104 :                                 function.modifiers = CCodeModifiers.EXTERN;
     154          104 :                                 requires_vala_extern = true;
     155              :                         }
     156          104 :                         function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*"));
     157          104 :                         decl_space.add_function_declaration (function);
     158              :                 }
     159              : 
     160          343 :                 if (context.profile == Profile.GOBJECT) {
     161          332 :                         generate_auto_cleanup_clear (st, decl_space);
     162              :                 }
     163              :         }
     164              : 
     165          332 :         void generate_auto_cleanup_clear (Struct st, CCodeFile decl_space) {
     166          434 :                 if (st.is_disposable ()
     167          102 :                     && (context.header_filename == null|| decl_space.file_type == CCodeFileType.PUBLIC_HEADER
     168            0 :                         || (decl_space.file_type == CCodeFileType.INTERNAL_HEADER && st.is_internal_symbol ()))) {
     169          102 :                         string auto_cleanup_clear_func = get_ccode_destroy_function (st);
     170          102 :                         if (auto_cleanup_clear_func == null || auto_cleanup_clear_func == "") {
     171            0 :                                 Report.error (st.source_reference, "internal error: auto_cleanup_clear_func not available");
     172              :                         }
     173          102 :                         decl_space.add_type_member_declaration (new CCodeIdentifier ("G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (%s, %s)".printf (get_ccode_name (st), auto_cleanup_clear_func)));
     174          102 :                         decl_space.add_type_member_declaration (new CCodeNewline ());
     175              :                 }
     176              :         }
     177              : 
     178          380 :         public override void visit_struct (Struct st) {
     179          190 :                 push_context (new EmitContext (st));
     180          190 :                 push_line (st.source_reference);
     181              : 
     182          380 :                 var old_instance_finalize_context = instance_finalize_context;
     183          190 :                 instance_finalize_context = new EmitContext ();
     184              : 
     185          190 :                 generate_struct_declaration (st, cfile);
     186              : 
     187          190 :                 if (!st.is_internal_symbol ()) {
     188           31 :                         generate_struct_declaration (st, header_file);
     189              :                 }
     190          190 :                 if (!st.is_private_symbol ()) {
     191          189 :                         generate_struct_declaration (st, internal_header_file);
     192              :                 }
     193              : 
     194          190 :                 if (!st.is_boolean_type () && !st.is_integer_type () && !st.is_floating_type ()) {
     195          164 :                         if (st.is_disposable ()) {
     196           49 :                                 begin_struct_destroy_function (st);
     197              :                         }
     198              :                 }
     199              : 
     200          190 :                 st.accept_children (this);
     201              : 
     202          190 :                 if (!st.is_boolean_type () && !st.is_integer_type () && !st.is_floating_type ()) {
     203          164 :                         if (st.is_disposable ()) {
     204           49 :                                 add_struct_copy_function (st);
     205           49 :                                 add_struct_destroy_function (st);
     206              :                         }
     207              : 
     208          164 :                         if (!st.is_simple_type ()) {
     209          157 :                                 add_struct_dup_function (st);
     210          157 :                                 add_struct_free_function (st);
     211              :                         }
     212              :                 }
     213              : 
     214          192 :                 instance_finalize_context = old_instance_finalize_context;
     215              : 
     216          190 :                 pop_line ();
     217          190 :                 pop_context ();
     218              :         }
     219              : 
     220          314 :         void add_struct_dup_function (Struct st) {
     221          157 :                 var function = new CCodeFunction (get_ccode_dup_function (st), get_ccode_name (st) + "*");
     222          157 :                 if (st.access == SymbolAccessibility.PRIVATE) {
     223            1 :                         function.modifiers = CCodeModifiers.STATIC;
     224              :                 }
     225              : 
     226          157 :                 function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*"));
     227              : 
     228          157 :                 push_function (function);
     229              : 
     230          157 :                 ccode.add_declaration (get_ccode_name (st) + "*", new CCodeVariableDeclarator ("dup"));
     231              : 
     232          309 :                 if (context.profile == Profile.GOBJECT) {
     233              :                         // g_new0 needs glib.h
     234          152 :                         cfile.add_include ("glib.h");
     235          152 :                         var creation_call = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
     236          152 :                         creation_call.add_argument (new CCodeConstant (get_ccode_name (st)));
     237          152 :                         creation_call.add_argument (new CCodeConstant ("1"));
     238          152 :                         ccode.add_assignment (new CCodeIdentifier ("dup"), creation_call);
     239           10 :                 } else if (context.profile == Profile.POSIX) {
     240              :                         // calloc needs stdlib.h
     241            5 :                         cfile.add_include ("stdlib.h");
     242              : 
     243            5 :                         var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
     244            5 :                         sizeof_call.add_argument (new CCodeConstant (get_ccode_name (st)));
     245              : 
     246            5 :                         var creation_call = new CCodeFunctionCall (new CCodeIdentifier ("calloc"));
     247            5 :                         creation_call.add_argument (new CCodeConstant ("1"));
     248            5 :                         creation_call.add_argument (sizeof_call);
     249            5 :                         ccode.add_assignment (new CCodeIdentifier ("dup"), creation_call);
     250              :                 }
     251              : 
     252          314 :                 if (st.is_disposable ()) {
     253           49 :                         var copy_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_copy_function (st)));
     254           49 :                         copy_call.add_argument (new CCodeIdentifier ("self"));
     255           49 :                         copy_call.add_argument (new CCodeIdentifier ("dup"));
     256           49 :                         ccode.add_expression (copy_call);
     257              :                 } else {
     258          108 :                         cfile.add_include ("string.h");
     259              : 
     260          108 :                         var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
     261          108 :                         sizeof_call.add_argument (new CCodeConstant (get_ccode_name (st)));
     262              : 
     263          108 :                         var copy_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
     264          108 :                         copy_call.add_argument (new CCodeIdentifier ("dup"));
     265          108 :                         copy_call.add_argument (new CCodeIdentifier ("self"));
     266          108 :                         copy_call.add_argument (sizeof_call);
     267          108 :                         ccode.add_expression (copy_call);
     268              :                 }
     269              : 
     270          157 :                 ccode.add_return (new CCodeIdentifier ("dup"));
     271              : 
     272          157 :                 pop_function ();
     273              : 
     274          157 :                 cfile.add_function (function);
     275              :         }
     276              : 
     277          314 :         void add_struct_free_function (Struct st) {
     278          157 :                 var function = new CCodeFunction (get_ccode_free_function (st), "void");
     279          157 :                 if (st.is_private_symbol ()) {
     280            1 :                         function.modifiers = CCodeModifiers.STATIC;
     281          156 :                 } else if (context.hide_internal && st.is_internal_symbol ()) {
     282            0 :                         function.modifiers = CCodeModifiers.INTERNAL;
     283              :                 }
     284              : 
     285          157 :                 function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*"));
     286              : 
     287          157 :                 push_function (function);
     288              : 
     289          206 :                 if (st.is_disposable ()) {
     290           49 :                         var destroy_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_destroy_function (st)));
     291           49 :                         destroy_call.add_argument (new CCodeIdentifier ("self"));
     292           49 :                         ccode.add_expression (destroy_call);
     293              :                 }
     294              : 
     295          309 :                 if (context.profile == Profile.GOBJECT) {
     296              :                         // g_free needs glib.h
     297          152 :                         cfile.add_include ("glib.h");
     298          152 :                         var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
     299          152 :                         free_call.add_argument (new CCodeIdentifier ("self"));
     300          152 :                         ccode.add_expression (free_call);
     301           10 :                 } else if (context.profile == Profile.POSIX) {
     302              :                         // free needs stdlib.h
     303            5 :                         cfile.add_include ("stdlib.h");
     304            5 :                         var free_call = new CCodeFunctionCall (new CCodeIdentifier ("free"));
     305            5 :                         free_call.add_argument (new CCodeIdentifier ("self"));
     306            5 :                         ccode.add_expression (free_call);
     307              :                 }
     308              : 
     309          157 :                 pop_function ();
     310              : 
     311          157 :                 cfile.add_function (function);
     312              :         }
     313              : 
     314           98 :         void add_struct_copy_function (Struct st) {
     315           49 :                 var function = new CCodeFunction (get_ccode_copy_function (st), "void");
     316           49 :                 if (st.is_private_symbol ()) {
     317            0 :                         function.modifiers = CCodeModifiers.STATIC;
     318           49 :                 } else if (context.hide_internal && st.is_internal_symbol ()) {
     319            0 :                         function.modifiers = CCodeModifiers.INTERNAL;
     320              :                 }
     321              : 
     322           49 :                 function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*"));
     323           49 :                 function.add_parameter (new CCodeParameter ("dest", get_ccode_name (st) + "*"));
     324              : 
     325           49 :                 push_function (function);
     326              : 
     327           49 :                 var dest_struct = new GLibValue (SemanticAnalyzer.get_data_type_for_symbol (st), new CCodeIdentifier ("(*dest)"), true);
     328              :                 unowned Struct sym = st;
     329           54 :                 while (sym.base_struct != null) {
     330            5 :                         sym = sym.base_struct;
     331              :                 }
     332          217 :                 foreach (var f in sym.get_fields ()) {
     333          168 :                         if (f.binding == MemberBinding.INSTANCE) {
     334           84 :                                 var value = load_field (f, load_this_parameter ((TypeSymbol) st));
     335           84 :                                 if ((!(f.variable_type is DelegateType) || get_ccode_delegate_target (f)) && requires_copy (f.variable_type))  {
     336           50 :                                         value = copy_value (value, f);
     337           50 :                                         if (value == null) {
     338              :                                                 // error case, continue to avoid critical
     339            0 :                                                 continue;
     340              :                                         }
     341              :                                 }
     342           84 :                                 store_field (f, dest_struct, value, false);
     343              :                         }
     344              :                 }
     345              : 
     346           49 :                 pop_function ();
     347              : 
     348           49 :                 cfile.add_function (function);
     349              :         }
     350              : 
     351           98 :         void begin_struct_destroy_function (Struct st) {
     352           49 :                 push_context (instance_finalize_context);
     353              : 
     354           49 :                 var function = new CCodeFunction (get_ccode_destroy_function (st), "void");
     355           49 :                 if (st.is_private_symbol ()) {
     356            0 :                         function.modifiers = CCodeModifiers.STATIC;
     357           49 :                 } else if (context.hide_internal && st.is_internal_symbol ()) {
     358            0 :                         function.modifiers = CCodeModifiers.INTERNAL;
     359              :                 }
     360              : 
     361           49 :                 function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*"));
     362              : 
     363           49 :                 push_function (function);
     364              : 
     365           49 :                 pop_context ();
     366              :         }
     367              : 
     368           49 :         void add_struct_destroy_function (Struct st) {
     369              :                 unowned Struct sym = st;
     370           54 :                 while (sym.base_struct != null) {
     371            5 :                         sym = sym.base_struct;
     372              :                 }
     373           54 :                 if (st != sym) {
     374            5 :                         push_context (instance_finalize_context);
     375              : 
     376            5 :                         var destroy_func = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_destroy_function (sym)));
     377            5 :                         destroy_func.add_argument (new CCodeIdentifier ("self"));
     378            5 :                         ccode.add_expression (destroy_func);
     379              : 
     380            5 :                         pop_context ();
     381              :                 }
     382              : 
     383           49 :                 cfile.add_function (instance_finalize_context.ccode);
     384              :         }
     385              : }
     386              : 
        

Generated by: LCOV version 2.0-1