in SharpGen.Platform/CppParser.cs [624:712]
private CppStruct ParseStructOrUnion(XElement xElement, CppElement cppParent = null, int innerAnonymousIndex = 0)
{
var cppStruct = xElement.Annotation<CppStruct>();
if (cppStruct != null)
return cppStruct;
// Build struct name directly from the struct name or based on the parent
var structName = GetStructName(xElement, cppParent, innerAnonymousIndex);
// Create struct
cppStruct = new CppStruct(structName);
xElement.AddAnnotation(cppStruct);
var isUnion = (xElement.Name.LocalName == CastXml.TagUnion);
cppStruct.IsUnion = isUnion;
// Enter struct/union description
Logger.PushContext("{0}:[{1}]", xElement.Name.LocalName, cppStruct.Name);
var basesValue = xElement.AttributeValue("bases");
var bases = basesValue != null ? basesValue.Split(' ') : Enumerable.Empty<string>();
cppStruct.Base = GetStructDirectBase(bases);
// Parse all fields
var fieldOffset = 0;
var innerStructCount = 0;
foreach (var field in xElement.Elements())
{
if (field.Name.LocalName != CastXml.TagField)
continue;
// Parse the field
var cppField = ParseField(field, fieldOffset);
// Test if the field type is declared inside this struct or union
var fieldName = field.AttributeValue("name");
var fieldType = _mapIdToXElement[field.AttributeValue("type")];
if (fieldType.AttributeValue("context") == xElement.AttributeValue("id"))
{
var fieldSubStruct = ParseStructOrUnion(fieldType, cppStruct, innerStructCount++);
// If fieldName is empty, then we need to inline fields from the struct/union.
if (string.IsNullOrEmpty(fieldName))
{
// Make a copy in order to remove fields
var listOfSubFields = new List<CppField>(fieldSubStruct.Fields);
// Copy the current field offset
var lastFieldOffset = fieldOffset;
foreach (var subField in listOfSubFields)
{
subField.Offset = subField.Offset + fieldOffset;
cppStruct.Add(subField);
lastFieldOffset = subField.Offset;
}
// Set the current field offset according to the inlined fields
if (!isUnion)
fieldOffset = lastFieldOffset;
// Don't add the current field, as it is actually an inline struct/union
cppField = null;
}
else
{
// Get the type name from the inner-struct and set it to the field
cppField.TypeName = fieldSubStruct.Name;
_currentCppInclude.Add(fieldSubStruct);
}
}
// Go to next field offset if not in union
var goToNextFieldOffset = !isUnion;
// Add the field if any
if (cppField != null)
{
cppStruct.Add(cppField);
// TODO managed multiple bitfield group
// Current implem is only working with a single set of consecutive bitfield in the same struct
goToNextFieldOffset = goToNextFieldOffset && !cppField.IsBitField;
}
if (goToNextFieldOffset)
fieldOffset++;
}
// Leave struct
Logger.PopContext();
return cppStruct;
}