Esempio n. 1
0
        private void GenerateSubTypes(Type sourceType, out bool hasVariableSerializableLength)
        {
            hasVariableSerializableLength = false;

            // Check do we have all cpp types required to generate a type.
            //
            foreach (FieldInfo fieldInfo in sourceType.GetPublicInstanceFields())
            {
                if (fieldInfo.IsString())
                {
                    // Structure contains a string field.
                    //
                    hasVariableSerializableLength = true;
                }

                // For arrays, ensure the array element type has been generated.
                //
                Type fieldType = fieldInfo.IsFixedSizedArray() ? fieldInfo.FieldType.GetElementType() : fieldInfo.FieldType;

                if (CppTypeMapper.TryGetCppType(fieldType, out CppType cppType))
                {
                    // Cpp type has been generated, safe to use.
                    //
                    if (cppType.HasVariableData)
                    {
                        // Field type is variable length, so containing structure is also variable length.
                        //
                        hasVariableSerializableLength = true;
                    }

                    continue;
                }

                // Recursively generate field type.
                //
                if (!this.GenerateType(fieldType))
                {
                    // There are errors, however continue, so we can report on all of them in one shot.
                    //
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Generate the necessary code for a given type.
        /// </summary>
        /// <param name="sourceType"></param>
        /// <returns>True if there were no codegen errors.</returns>
        public bool GenerateType(Type sourceType)
        {
            if (CppTypeMapper.HasCppType(sourceType))
            {
                // We already generated a Cpp type.
                //
                return(true);
            }

            CppTypeMapper.DeclareType(sourceType);

            GenerateSubTypes(sourceType, out bool hasVariableSerializableLength);

            // Failed to generate required field types.
            //
            if (CodeGenErrors.Any())
            {
                return(false);
            }

            DefineCppType(
                sourceType,
                hasVariableSerializableLength,
                out List <CppField> cppFields,
                out List <CppConstField> cppConstFields);

            // We are unable to generate code, return early.
            //
            if (CodeGenErrors.Any())
            {
                return(false);
            }

            if (CodeWriter.Accept(sourceType))
            {
                WriteCode(sourceType, cppFields, cppConstFields);
            }

            return(true);
        }
Esempio n. 3
0
        private bool IsSupportedFieldType(FieldInfo fieldInfo, out CppType cppFieldType)
        {
            Type fieldType = fieldInfo.IsFixedSizedArray() ? fieldInfo.FieldType.GetElementType() : fieldInfo.FieldType;

            return(CppTypeMapper.TryGetCppType(fieldType, out cppFieldType));
        }
Esempio n. 4
0
        private void DefineCppType(Type sourceType, bool hasVariableSerializableLength, out List <CppField> cppFields)
        {
            cppFields = new List <CppField>();

            // Build list of structure properties.
            // Calculate fields offsets for flatten structure.
            //
            uint cppStructOffset = 0;

            // Calculate the type alignment, this is required when type is used as inner type in other types.
            //
            uint alignment = 1;

            // Export public instance fields.
            //
            foreach (FieldInfo fieldInfo in sourceType.GetPublicInstanceFields())
            {
                if (sourceType.IsCodegenConfigType() && !fieldInfo.IsScalarSetting())
                {
                    AddUntaggedOrNoneScalarPublicSettingRegistryField(sourceType, fieldInfo);
                    continue;
                }

                if (!IsSupportedFieldType(fieldInfo, out CppType cppFieldType))
                {
                    AddUnsupportedFieldTypeError(sourceType, fieldInfo);
                    continue;
                }

                if (!IsValidAlignmentSizeAttribute(fieldInfo, out uint customFieldAlignment))
                {
                    AddInvalidAlignmentSizeError(sourceType, fieldInfo);
                    continue;
                }

                // Align the field offset and update type aligment.
                //
                uint fieldAlignment = customFieldAlignment == 0
                    ? cppFieldType.Alignment
                    : customFieldAlignment;

                if (fieldAlignment != 0)
                {
                    cppStructOffset = CppTypeMapper.AlignSize(cppStructOffset, fieldAlignment);

                    alignment = Math.Max(alignment, fieldAlignment);
                }

                // Calculate type size.
                //
                uint typeSize = cppFieldType.TypeSize;

                // Calculate field size in case when we have an array.
                //
                if (fieldInfo.IsFixedSizedArray())
                {
                    if (!fieldInfo.IsInitOnly)
                    {
                        AddMissingFieldReadonlyModifierError(sourceType, fieldInfo);
                    }

                    if (!sourceType.IsClass)
                    {
                        AddIncorrectDefinitionError(sourceType, fieldInfo);
                    }

                    FixedSizeArrayAttribute arrayAttribute = fieldInfo.GetCustomAttribute <FixedSizeArrayAttribute>();

                    // Adjust the structure size.
                    //
                    typeSize += typeSize * (arrayAttribute.Length - 1);
                }

                cppFields.Add(
                    new CppField
                {
                    CppStructOffset = cppStructOffset,
                    FieldInfo       = fieldInfo,
                    CppType         = cppFieldType,
                });

                cppStructOffset += typeSize;
            }

            if (CodeGenErrors.Any())
            {
                // We are unable to generate code, return early.
                //
                return;
            }

            uint paddingSize = 0;

            // Align structure size unless it has explicitly defined size.
            //
            if (sourceType.StructLayoutAttribute.Size == 0)
            {
                cppStructOffset = CppTypeMapper.AlignSize(cppStructOffset, alignment);
            }
            else
            {
                // Explicitly defined size, calculate padding.
                //
                paddingSize      = (uint)sourceType.StructLayoutAttribute.Size - cppStructOffset;
                cppStructOffset += paddingSize;
            }

            // Check the final structure alignment.
            //
            AlignAttribute alignmentAttribute = sourceType.GetCustomAttribute <AlignAttribute>();

            if (alignmentAttribute != null)
            {
                alignment = alignmentAttribute.Size;
            }

            // Define a new Cpp type.
            //
            CppTypeMapper.DefineType(
                sourceType,
                cppTypeSize: cppStructOffset,
                aligment: alignment,
                paddingSize: paddingSize,
                hasVariableSerializableLength: hasVariableSerializableLength);
        }