private CppStruct ParseStructOrUnion()

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;
        }