[vala] Add has_copy_function and has_destroy_function struct attributes



commit 7092325a49472d5c108adb5f3e96623c75b77bbd
Author: Jürg Billeter <j bitron ch>
Date:   Sun Sep 13 20:38:46 2009 +0200

    Add has_copy_function and has_destroy_function struct attributes

 codegen/valaccodebasemodule.vala |  121 ++++++++++++++++++++++++++++++++++++++
 vala/valacodewriter.vala         |   12 ++++
 vala/valastruct.vala             |   10 +++
 vapigen/valagidlparser.vala      |   24 ++++++++
 4 files changed, 167 insertions(+), 0 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 0df998c..aa00179 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -1990,6 +1990,10 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 
 			var st = value_type.data_type as Struct;
 			if (st != null && st.is_disposable ()) {
+				if (!st.has_copy_function) {
+					generate_struct_copy_function (st);
+				}
+
 				var copy_call = new CCodeFunctionCall (new CCodeIdentifier (st.get_copy_function ()));
 				copy_call.add_argument (new CCodeIdentifier ("self"));
 				copy_call.add_argument (new CCodeIdentifier ("dup"));
@@ -2098,6 +2102,9 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 					}
 				} else {
 					var st = (Struct) type.data_type;
+					if (!st.has_destroy_function) {
+						generate_struct_destroy_function (st);
+					}
 					unref_function = st.get_destroy_function ();
 				}
 			}
@@ -2903,6 +2910,10 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 			copy_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr));
 			copy_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp));
 
+			if (!st.has_copy_function) {
+				generate_struct_copy_function (st);
+			}
+
 			var ccomma = new CCodeCommaExpression ();
 
 			if (st.get_copy_function () == "g_value_copy") {
@@ -4261,6 +4272,116 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		result.add_argument (expr);
 		return result;
 	}
+
+	void generate_struct_destroy_function (Struct st) {
+		if (source_declarations.add_declaration (st.get_destroy_function ())) {
+			// only generate function once per source file
+			return;
+		}
+
+		var function = new CCodeFunction (st.get_destroy_function (), "void");
+		function.modifiers = CCodeModifiers.STATIC;
+		function.add_parameter (new CCodeFormalParameter ("self", st.get_cname () + "*"));
+
+		var cblock = new CCodeBlock ();
+		foreach (Field f in st.get_fields ()) {
+			if (f.binding == MemberBinding.INSTANCE) {
+				if (requires_destroy (f.field_type)) {
+					var lhs = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), f.get_cname ());
+
+					var this_access = new MemberAccess.simple ("this");
+					this_access.value_type = get_data_type_for_symbol ((TypeSymbol) f.parent_symbol);
+					this_access.ccodenode = new CCodeIdentifier ("(*self)");
+
+					var ma = new MemberAccess (this_access, f.name);
+					ma.symbol_reference = f;
+					cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (lhs, f.field_type, ma)));
+				}
+			}
+		}
+
+		source_declarations.add_type_member_declaration (function.copy ());
+		function.block = cblock;
+		source_type_member_definition.append (function);
+	}
+
+	void generate_struct_copy_function (Struct st) {
+		if (source_declarations.add_declaration (st.get_copy_function ())) {
+			// only generate function once per source file
+			return;
+		}
+
+		var function = new CCodeFunction (st.get_copy_function (), "void");
+		function.modifiers = CCodeModifiers.STATIC;
+		function.add_parameter (new CCodeFormalParameter ("self", "const " + st.get_cname () + "*"));
+		function.add_parameter (new CCodeFormalParameter ("dest", st.get_cname () + "*"));
+
+		int old_next_temp_var_id = next_temp_var_id;
+		var old_temp_vars = temp_vars;
+		var old_temp_ref_vars = temp_ref_vars;
+		var old_variable_name_map = variable_name_map;
+		next_temp_var_id = 0;
+		temp_vars = new ArrayList<LocalVariable> ();
+		temp_ref_vars = new ArrayList<LocalVariable> ();
+		variable_name_map = new HashMap<string,string> (str_hash, str_equal);
+
+		var cblock = new CCodeBlock ();
+		var cfrag = new CCodeFragment ();
+		cblock.add_statement (cfrag);
+
+		foreach (Field f in st.get_fields ()) {
+			if (f.binding == MemberBinding.INSTANCE) {
+				CCodeExpression copy = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), f.name);
+				if (requires_copy (f.field_type))  {
+					var this_access = new MemberAccess.simple ("this");
+					this_access.value_type = get_data_type_for_symbol ((TypeSymbol) f.parent_symbol);
+					this_access.ccodenode = new CCodeIdentifier ("(*self)");
+					var ma = new MemberAccess (this_access, f.name);
+					ma.symbol_reference = f;
+					copy = get_ref_cexpression (f.field_type, copy, ma, f);
+				}
+				var dest = new CCodeMemberAccess.pointer (new CCodeIdentifier ("dest"), f.name);
+
+				var array_type = f.field_type as ArrayType;
+				if (array_type != null && array_type.fixed_length) {
+					// fixed-length (stack-allocated) arrays
+					source_declarations.add_include ("string.h");
+
+					var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
+					sizeof_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
+					var size = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeConstant ("%d".printf (array_type.length)), sizeof_call);
+
+					var array_copy_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
+					array_copy_call.add_argument (dest);
+					array_copy_call.add_argument (copy);
+					array_copy_call.add_argument (size);
+					cblock.add_statement (new CCodeExpressionStatement (array_copy_call));
+				} else {
+					cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (dest, copy)));
+
+					if (array_type != null && !f.no_array_length) {
+						for (int dim = 1; dim <= array_type.rank; dim++) {
+							var len_src = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), get_array_length_cname (f.name, dim));
+							var len_dest = new CCodeMemberAccess.pointer (new CCodeIdentifier ("dest"), get_array_length_cname (f.name, dim));
+							cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (len_dest, len_src)));
+						}
+					}
+				}
+			}
+		}
+
+		append_temp_decl (cfrag, temp_vars);
+		temp_vars.clear ();
+
+		next_temp_var_id = old_next_temp_var_id;
+		temp_vars = old_temp_vars;
+		temp_ref_vars = old_temp_ref_vars;
+		variable_name_map = old_variable_name_map;
+
+		source_declarations.add_type_member_declaration (function.copy ());
+		function.block = cblock;
+		source_type_member_definition.append (function);
+	}
 }
 
 // vim:sw=8 noet
diff --git a/vala/valacodewriter.vala b/vala/valacodewriter.vala
index 5a9cb10..ee294e5 100644
--- a/vala/valacodewriter.vala
+++ b/vala/valacodewriter.vala
@@ -320,6 +320,14 @@ public class Vala.CodeWriter : CodeVisitor {
                         write_string ("use_const = false, ");
                 }
 
+                if (!st.has_copy_function) {
+                        write_string ("has_copy_function = false, ");
+                }
+
+                if (!st.has_destroy_function) {
+                        write_string ("has_destroy_function = false, ");
+                }
+
 		write_string ("cheader_filename = \"%s\")]".printf (get_cheaders(st)));
 		write_newline ();
 
@@ -627,6 +635,10 @@ public class Vala.CodeWriter : CodeVisitor {
 				}
 
 				write_string ("array_length = false");
+
+				if (f.array_null_terminated) {
+					write_string (", array_null_terminated = true");
+				}
 			}
 
 			write_string (")]");
diff --git a/vala/valastruct.vala b/vala/valastruct.vala
index 17ed9ec..2676322 100644
--- a/vala/valastruct.vala
+++ b/vala/valastruct.vala
@@ -96,6 +96,10 @@ public class Vala.Struct : TypeSymbol {
 
 	public bool signed { get; set; default = true; }
 
+	public bool has_copy_function { get; set; default = true; }
+
+	public bool has_destroy_function { get; set; default = true; }
+
 	/**
 	 * Creates a new struct.
 	 *
@@ -432,9 +436,15 @@ public class Vala.Struct : TypeSymbol {
 		if (a.has_argument ("copy_function")) {
 			set_copy_function (a.get_string ("copy_function"));
 		}
+		if (a.has_argument ("has_copy_function")) {
+			has_copy_function = a.get_bool ("has_copy_function");
+		}
 		if (a.has_argument ("destroy_function")) {
 			set_destroy_function (a.get_string ("destroy_function"));
 		}
+		if (a.has_argument ("has_destroy_function")) {
+			has_destroy_function = a.get_bool ("has_destroy_function");
+		}
 		if (a.has_argument ("use_const")) {
 			use_const = a.get_bool ("use_const");
 		}
diff --git a/vapigen/valagidlparser.vala b/vapigen/valagidlparser.vala
index 914517d..b9f0214 100644
--- a/vapigen/valagidlparser.vala
+++ b/vapigen/valagidlparser.vala
@@ -436,6 +436,14 @@ public class Vala.GIdlParser : CodeVisitor {
 							}
 						} else if (nv[0] == "type_id") {
 							st.set_type_id (eval (nv[1]));
+						} else if (nv[0] == "has_copy_function") {
+							if (eval (nv[1]) == "0") {
+								st.has_copy_function = false;
+							}
+						} else if (nv[0] == "has_destroy_function") {
+							if (eval (nv[1]) == "0") {
+								st.has_destroy_function = false;
+							}
 						}
 					}
 				}
@@ -727,6 +735,14 @@ public class Vala.GIdlParser : CodeVisitor {
 							if (eval (nv[1]) == "0") {
 								st.use_const = false;
 							}
+						} else if (nv[0] == "has_copy_function") {
+							if (eval (nv[1]) == "0") {
+								st.has_copy_function = false;
+							}
+						} else if (nv[0] == "has_destroy_function") {
+							if (eval (nv[1]) == "0") {
+								st.has_destroy_function = false;
+							}
 						}
 					}
 				}
@@ -1877,6 +1893,7 @@ public class Vala.GIdlParser : CodeVisitor {
 
 		string cheader_filename = null;
 		string ctype = null;
+		bool array_null_terminated = false;
 
 		var attributes = get_attributes ("%s.%s".printf (current_data_type.get_cname (), node.name));
 		if (attributes != null) {
@@ -1909,6 +1926,10 @@ public class Vala.GIdlParser : CodeVisitor {
 					cheader_filename = eval (nv[1]);
 				} else if (nv[0] == "ctype") {
 					ctype = eval (nv[1]);
+				} else if (nv[0] == "array_null_terminated") {
+					if (eval (nv[1]) == "1") {
+						array_null_terminated = true;
+					}
 				}
 			}
 		}
@@ -1943,6 +1964,9 @@ public class Vala.GIdlParser : CodeVisitor {
 		}
 
 		field.no_array_length = true;
+		if (array_null_terminated) {
+			field.array_null_terminated = true;
+		}
 
 		return field;
 	}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]