in TssCodeGen/src/CGenDotNet.cs [260:504]
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()