static List <TpmStruct> GetUnionMemberStructures(UnionField uf) { var unionList = new List <TpmStruct>(); foreach (var s in TpmTypes.Get <TpmStruct>().Where(s => !s.IsCmdStruct())) { foreach (TpmUnion u in s.ContainingUnions) { if (u.Name == uf.TypeName) { unionList.Add(s); } } } return(unionList); }
// The spec uses these two sorts of tagged structure commonly // { len, array[len] } and // { selector, [select]union } // This routine changes references to these sorts of structure to an embedded form. public static void FlattenTaggedStructures() { // Build the list of tagged structures List <TpmStruct> taggedStructs = new List <TpmStruct>(); foreach (TpmType tp in TpmTypes.TheTypes) { var s = tp as TpmStruct; if (s == null) { continue; } var t = s; while (t != null && t.Fields.Count != 2) { t = t.DerivedFrom; } if (t == null || s.SpecName.IsOneOf(DontFlatten)) { continue; } if ((t.Fields[0].MarshalType == MarshalType.ArrayCount) || (t.Fields[0].MarshalType == MarshalType.UnionSelector) || (t.Fields[0].MarshalType == MarshalType.LengthOfStruct) ) { taggedStructs.Add(s); } } // find references to the tagged structures and replace them foreach (TpmType tp in TpmTypes.TheTypes) { if (!(tp is TpmStruct)) { continue; } TpmStruct t = (TpmStruct)tp; for (int j = 0; j < t.Fields.Count; j++) { StructField origField = t.Fields[j]; if (origField.IsArray()) { continue; // Don't flatten arrays } var toEmbed = origField.Type as TpmStruct; if (taggedStructs.Contains(toEmbed)) { // If a structure to flatten is one without fields of its own, // but is derived from a flattenable one, unwind the inheritance chain. while (toEmbed != null && toEmbed.Fields.Count != 2) { toEmbed = toEmbed.DerivedFrom; } StructField tagToEmbed = toEmbed.Fields[0]; Debug.Assert(origField.MinVal == null || origField.MinVal == tagToEmbed.MinVal); Debug.Assert(origField.MaxVal == null || origField.MaxVal == tagToEmbed.MaxVal); var bufToEmbed = toEmbed.Fields[1]; string newTagName = origField.Name + Helpers.Capitalize(tagToEmbed.Name); string newBufTypeName = bufToEmbed.Type.SpecName; var newTagField = new StructField(tagToEmbed, newTagName); t.Fields[j] = newTagField; switch (tagToEmbed.MarshalType) { case MarshalType.UnionSelector: { var newField = new UnionField(newBufTypeName, origField.Name, origField.Comment, newTagName, t); t.Fields.Insert(j + 1, newField); break; } case MarshalType.ArrayCount: { var newField = new VariableLengthArray(newBufTypeName, origField.Name, origField.Comment, newTagName, t); t.Fields.Insert(j + 1, newField); break; } case MarshalType.LengthOfStruct: { var newField = new StructField(newBufTypeName, origField.Name, origField.Comment); t.Fields.Insert(j + 1, newField); newTagField.MarshalType = MarshalType.LengthOfStruct; newTagField.SizedField = newField; newField.MarshalType = MarshalType.SizedStruct; newField.SizeTagField = newTagField; break; } default: throw new Exception(""); } } // j-loop } } }
void GenStructure(TpmStruct s) { bool hasBase = s.DerivedFrom != null; // Has a non-trivial base class? string className = s.Name; string classBases = hasBase ? s.DerivedFrom.Name : "TpmStructureBase"; // Here "implements" is as opposed to "inherits and overrides" bool implementsUnionInterfaces = !s.IsCmdStruct() && !hasBase && s.ContainingUnions.Count > 0; Debug.Assert(s.DerivedFrom == null || s.DerivedFrom.ContainingUnions.Count >= s.ContainingUnions.Count); if (implementsUnionInterfaces) { foreach (TpmUnion u in s.ContainingUnions) { classBases += ", " + u.Name; } } WriteComment(s); Write("[DataContract]"); var knownTypes = GetKnownTypes(s); foreach (TpmType kt in knownTypes) { Write($"[KnownType(typeof({kt.Name}))]"); } string specName = s.Info.IsRequest() ? s.SpecName.Substring(5).Replace("_REQUEST", "_In") : s.Info.IsResponse() ? s.SpecName.Replace("Response", "_Out") : s.SpecName; Write($"[SpecTypeName(\"{specName}\")]"); Write($"public partial class {className}: {classBases}"); TabIn("{"); if (s.DerivedFrom != null) { Debug.Assert(!s.IsCmdStruct()); //--------------------------------------- // Constructors var fields = new List <StructField>(); TpmStruct b = s; do { fields.AddRange(b.NonTagFields); b = b.DerivedFrom; } while (b != null); // Default constructor Write($"public {className}() {{}}"); Write(""); if (fields.Count != 0) { // Copy-constructor WriteLine("public {0}({0} _{0}) : base(_{0}) {{}}", className); Write(""); // Member-wise constructor GenMemeberwiseCtorPrototype(className, fields); if (fields.Count == 1) { Write($" : base(_{fields.First().Name}) {{}}"); } else { string baseInitList = string.Join(", ", fields.ConvertAll(f => "_" + f.Name)); Write(""); Write($" : base({baseInitList})"); Write("{}"); } Write(""); } GenGetUnionSelector(s, implementsUnionInterfaces); GenCloningMethods(s.Name); // end of class TabOut("}"); return; } // if (s.DerivedFrom != null) // // Member fields // bool onlyStaticFields = true; int idx = 0; foreach (StructField f in s.Fields) { var tag = f.SizeTagField; if (f.SizedField == null) { WriteComment(f); WriteConstraints(f); } onlyStaticFields = false; switch (f.MarshalType) { case MarshalType.ArrayCount: case MarshalType.LengthOfStruct: --idx; break; case MarshalType.UnionSelector: { Debug.Assert(f.RelatedUnion.MarshalType == MarshalType.UnionObject); Debug.Assert(f.RelatedUnion.UnionSelector == f); var unionField = f.RelatedUnion; var u = (TpmUnion)unionField.Type; Write($"[MarshalAs({idx}, MarshalType.UnionSelector)]"); TabIn($"public {f.TypeName} {f.Name} {{"); if (u.NullSelector == null) { Write($"get {{ return {unionField.Name}.GetUnionSelector(); }}"); } else { Write($"get {{ return {unionField.Name} != null ? {unionField.Name}.GetUnionSelector() : {u.NullSelector.QualifiedName}; }}"); } TabOut("}"); // property break; } case MarshalType.Normal: case MarshalType.SizedStruct: { if (tag == null) { Write($"[MarshalAs({idx})]"); } else { Write($"[MarshalAs({idx}, MarshalType.SizedStruct, \"{tag.Name}\", {tag.Type.GetSize()})]"); } WriteFieldDef(f, " { get; set; }"); break; } case MarshalType.UnionObject: { UnionField fx = (UnionField)f; Write($"[MarshalAs({idx}, MarshalType.Union, \"{fx.UnionSelector.Name}\")]"); WriteFieldDef(f, " { get; set; }"); break; } case MarshalType.VariableLengthArray: case MarshalType.SpecialVariableLengthArray: { string marshalType = Enum.GetName(typeof(MarshalType), f.MarshalType); Write($"[MarshalAs({idx}, MarshalType.{marshalType}, \"{tag.Name}\", {tag.Type.GetSize()})]"); WriteFieldDef(f); break; } case MarshalType.EncryptedVariableLengthArray: { Write($"[MarshalAs({idx}, MarshalType.EncryptedVariableLengthArray)]"); WriteFieldDef(f); break; } case MarshalType.ConstantValue: { string val = TargetLang.TranslateConstExpr(f.Domain[0, Constraint.Type.Single]); Write($"[MarshalAs({idx})]"); WriteFieldDef(f, $" = {val};"); break; } default: throw new Exception(); } ++idx; } // foreach field if (onlyStaticFields && s.Fields.Count > 0) { // end of class TabOut("}"); return; } // Default constructor var fieldsToInit = s.NonDefaultInitFields; Write(""); Write($"public {className}()", false); if (fieldsToInit.Count() == 0) { Write(" {}"); } else if (fieldsToInit.Count() == 1) { var f = fieldsToInit[0]; Write($" {{ {f.Name} = {f.GetInitVal()}; }}"); } else { TabIn("{"); foreach (StructField f in fieldsToInit) { Write($"{f.Name} = {f.GetInitVal()};"); } TabOut("}"); } // Copy constructor if (!s.Info.IsRequest()) { var fields = s.NonTagFields; if (fields.Count() != 0) { Write(""); Write($"public {className}({className} src)", false); if (fields.Count() == 1 && s.SpecName != "TPM_HANDLE") { string field = fields.First().Name; Write($" {{ {field} = src.{field}; }}"); } else { Write(""); TabIn("{"); foreach (StructField f in fields) { Write($"{f.Name} = src.{f.Name};"); } // special case if (s.SpecName == "TPM_HANDLE") { Write("Auth = src.Auth;"); TabIn("if (src.Name != null)"); Write("Name = Globs.CopyData(src.Name);"); TabOut(); } TabOut("}"); } } } // Member-wise constructor if (!s.Info.IsResponse()) { var fields = s.NonTagFields; if (fields.Count() != 0) { GenMemeberwiseCtorPrototype(className, fields); if (fields.Count() == 1) { string fName = fields.First().Name; Write($" {{ {fName} = _{fName}; }}"); } else { TabIn("{"); foreach (StructField f in fields) { Write($"{f.Name} = _{f.Name};"); } TabOut("}"); } } } GenGetUnionSelector(s); GenCloningMethods(s.Name); TabOut("}"); // end of class } // GenStructure()