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. // } } }
/// <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); }
private bool IsSupportedFieldType(FieldInfo fieldInfo, out CppType cppFieldType) { Type fieldType = fieldInfo.IsFixedSizedArray() ? fieldInfo.FieldType.GetElementType() : fieldInfo.FieldType; return(CppTypeMapper.TryGetCppType(fieldType, out cppFieldType)); }
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); }