namespace GtkSharp.Generation { using System; using System.Collections; using System.IO; using System.Xml; using System.Collections.Generic; public class UnionSubstruct { List fields; XmlElement Elem; bool is_valid; bool unique_field; public string abi_info_name; public UnionSubstruct(XmlElement elem, ClassBase container_type, string abi_info_name) { fields = new List (); Elem = elem; is_valid = true; unique_field = false; if (Elem.Name == "struct") { foreach (XmlElement child_field in elem.ChildNodes) { if (child_field.Name != "field") { is_valid = false; continue; } fields.Add(new StructABIField (child_field, container_type, abi_info_name)); } } else if (Elem.Name == "field") { fields.Add(new StructABIField (Elem, container_type, abi_info_name)); unique_field = true; } } public string GenerateGetSize(string indent) { var size = indent += "new List() {"; var is_first = true; foreach (StructABIField field in fields) { if (!is_first) size += ","; is_first = false; size += "\"" + field.CName + "\""; } return size + "}"; } public void EnsureParentStructName (string parent_name) { var name = Elem.GetAttribute("name"); if (!unique_field) { parent_name = parent_name + '.' + name; } StructABIField next_field = null; foreach (var field in fields) { field.parent_structure_name = parent_name; } } public StructField Generate(GenerationInfo gen_info, string indent, string parent_name, StructABIField prev_field, StructABIField next, string struct_parent_name, TextWriter tw) { StreamWriter sw = gen_info.Writer; var name = Elem.GetAttribute("name"); var cname = Elem.GetAttribute("cname"); if (!unique_field) { parent_name = parent_name + '.' + name; } StructABIField next_field = null; sw.WriteLine(indent + "// union struct " + parent_name); for(int i=0; i < fields.Count; i++) { var field = fields[i]; next_field = fields.Count > i + 1 ? fields[i + 1] : null; field.parent_structure_name = parent_name; field.Generate(gen_info, indent, prev_field, next_field, struct_parent_name, tw); prev_field = field; } sw.WriteLine(indent + "// End " + parent_name); sw.WriteLine(); return prev_field; } } public class UnionABIField : StructABIField { bool is_valid; XmlElement Elem; protected List substructs = new List (); public UnionABIField (XmlElement elem, ClassBase container_type, string info_name) : base (elem, container_type, info_name) { Elem = elem; is_valid = true; foreach (XmlElement union_child in elem.ChildNodes) { substructs.Add(new UnionSubstruct(union_child, container_type, abi_info_name)); } } public override StructABIField Generate (GenerationInfo gen_info, string indent, StructABIField prev_field, StructABIField next_field, string parent_name, TextWriter tw) { StreamWriter sw = gen_info.Writer; var name = Elem.GetAttribute("name"); var cname = Elem.GetAttribute("cname"); foreach (UnionSubstruct _struct in substructs) _struct.EnsureParentStructName(cname); foreach (UnionSubstruct _struct in substructs) { _struct.Generate(gen_info, indent + "\t", cname, prev_field, next_field, parent_name, tw); } base.Generate(gen_info, indent, prev_field, next_field, parent_name, null); return this; } public override string GenerateGetSizeOf(string indent) { string res = indent + "new List>() { // union " + Elem.GetAttribute("cname") + "\n"; bool first = true; indent += "\t\t\t"; foreach (UnionSubstruct _struct in substructs) { if (!first) res += ",\n"; first = false; res += _struct.GenerateGetSize(indent + "\t\t\t"); } res += "\n" + indent + "\t\t }"; return res; } public override bool Validate (LogWriter log) { if (!is_valid) { log.Warn("Can't generate ABI compatible union"); } return is_valid; } } }