in TssCodeGen/src/CGenCpp.cs [166:348]
void GenStructDecl(TpmStruct s)
{
bool hasBase = s.DerivedFrom != null; // Has a non-trivial base class?
string className = s.Name;
if (IsTypedefStruct(s))
{
Debug.Assert(s.Fields.Count == 0);
WriteComment(s);
Write($"typedef {s.DerivedFrom.Name} {className};");
Write("");
return;
}
string classBases = hasBase ? s.DerivedFrom.Name
: !s.IsCmdStruct() ? "TpmStructure"
: s.Info.IsRequest() ? "ReqStructure" : "RespStructure";
string virt = "";
// If this struct is not derived from another one and is a member of one or more unions,
// it must implement the corresponding union interfaces
if (!s.IsCmdStruct() && !hasBase && s.ContainingUnions.Count > 0)
{
foreach (var u in s.ContainingUnions)
classBases += ", public " + u.Name;
virt = "virtual ";
}
WriteComment(s);
Write($"class _DLLEXP_ {className} : public {virt}{classBases}");
Write("{");
TabIn("public:");
//
// Fields
//
TpmField conversionSource = null;
foreach (var f in s.NonSizeFields)
{
if (f.MarshalType == MarshalType.ConstantValue)
// No member field for a constant tag
continue;
WriteComment(f);
if (f.MarshalType == MarshalType.UnionSelector)
{
var unionField = f.RelatedUnion;
var u = (TpmUnion)unionField.Type;
Write($"public: {f.TypeName} {f.Name}() const {{ ", false);
if (u.NullSelector == null)
Write($"return {unionField.Name}->GetUnionSelector(); }}");
else
{
Write($"return {unionField.Name} ? {unionField.Name}->GetUnionSelector()" +
$" : {u.NullSelector.QualifiedName}; }}");
}
continue;
}
Write($"{TransType(f)} {f.Name};");
}
TabOut("");
TabIn("public:");
//
// Default constructor
//
var fieldsToInit = s.NonDefaultInitFields;
Write($"{className}()", false);
if (fieldsToInit.Count() == 0)
Write(" {}");
else if (fieldsToInit.Count() == 1)
Write($" {{ {fieldsToInit[0].Name} = {fieldsToInit[0].GetInitVal()}; }}");
else
{
TabIn("{");
foreach (StructField f in fieldsToInit)
Write($"{f.Name} = {f.GetInitVal()};");
TabOut("}");
}
//
// Member-wise constructor
//
var ctorParams = s.FieldHolder.NonTagFields;
if (!s.Info.IsResponse() && ctorParams.Count() != 0)
{
string baseClass = hasBase ? s.DerivedFrom.Name : "TpmStructure";
string ctorParamList = string.Join(", ", ctorParams.Select(p => $"{CtorParamTypeFor(p)} _{p.Name}"));
Write($"{className}({ctorParamList})");
if (hasBase)
{
string ctorParamNamesList = string.Join(", ", ctorParams.Select(p => "_" + p.Name));
Write($" : {baseClass}({ctorParamNamesList})");
}
else
{
string memInitList = string.Join(", ", ctorParams.Select(p => p.Type is TpmUnion
? $"{p.Name}(dynamic_cast<{p.Type.Name}*>(_{p.Name}.Clone()))"
: $"{p.Name}(_{p.Name})"
));
Write($" : {memInitList}");
}
Write("{}");
}
if (conversionSource != null)
{
Write("");
Write($"operator ByteVec&() {{ return {conversionSource.Name}; }}");
Write($"operator const ByteVec&() const {{ return {conversionSource.Name}; }}");
}
//
// Union interface: TpmUnion.GetUnionSelector()
//
GenGetUnionSelector(s);
//
// Marshaling
//
Write("");
GenMarshalingMethod(true, s, true);
GenMarshalingMethod(false, s, true);
string comment = AsSummary("Static marshaling helper");
WriteComment(comment);
Write($"static {className} fromTpm(TpmBuffer& buf) {{ return buf.createObj<{className}>(); }}");
WriteComment(comment);
Write($"static {className} fromBytes(const ByteVec& buf) {{ return TpmStructure::fromBytes<{className}>(buf); }}");
//
// Serialization
//
Write("");
Write($"virtual const char* TypeName () const {{ return \"{className}\"; }}");
Write("");
Write("using TpmStructure::Serialize;");
Write("using TpmStructure::Deserialize;");
GenMarshalingMethod(true, s, true, true);
GenMarshalingMethod(false, s, true, true);
//
// Cloning and metadata
//
Write("");
Write($"virtual TpmStructure* Clone() const {{ return new {className}(*this); }}");
var info = s.IsCmdStruct() ? s.Info as CmdStructInfo : null;
if (info != null && (info.NumHandles != 0 || info.SessEncSizeLen != 0))
{
TabOut("");
TabIn("protected:");
if (info.NumHandles != 0)
{
Write($"virtual uint16_t numHandles() const {{ return {info.NumHandles}; }}");
if (info.IsRequest())
{
string handles = string.Join(", ", s.Fields.Take(info.NumHandles).Select(f => f.Name));
Write($"virtual uint16_t numAuthHandles() const {{ return {info.NumAuthHandles}; }}");
Write($"virtual vector<TPM_HANDLE> getHandles() const {{ return {{{handles}}}; }}");
}
else
{
Debug.Assert(info.NumHandles == 1 && info.NumAuthHandles == 0);
Write($"virtual TPM_HANDLE getHandle() const {{ return {s.Fields[0].Name}; }}");
Write($"virtual void setHandle(const TPM_HANDLE& h) {{ {s.Fields[0].Name} = h; }}");
}
}
if (info.SessEncSizeLen != 0)
{
Debug.Assert(info.SessEncValLen != 0);
Write("");
Write($"virtual SessEncInfo sessEncInfo() const {{ return {{{info.SessEncSizeLen}, {info.SessEncValLen}}}; }}");
}
}
InsertSnip(s.Name);
TabOut($"}}; // class {className}");
} // GenStruct()