/// <summary> /// Extracts all fields from the user type. /// </summary> /// <param name="factory">The user type factory.</param> /// <param name="generationFlags">The user type generation flags.</param> protected override IEnumerable <UserTypeField> ExtractFields(UserTypeFactory factory, UserTypeGenerationFlags generationFlags) { ExportStaticFields = true; var fields = Symbol.Fields.OrderBy(s => s.Name).ToArray(); bool useThisClass = generationFlags.HasFlag(UserTypeGenerationFlags.UseDirectClassAccess); HashSet <string> usedNames = new HashSet <string>(); foreach (var field in fields) { if (string.IsNullOrEmpty(field.Type.Name)) { continue; } if (IsFieldFiltered(field)) { continue; } field.PropertyName = NormalizeSymbolNamespace(UserTypeField.GetPropertyName(field, this)); while (usedNames.Contains(field.PropertyName)) { field.PropertyName += "_"; } if (field.Name.Contains("@") || field.PropertyName.Length > 511) { // Skip names containing '@' continue; } // Skip fields that are actual values of enum values if (field.Type.Tag == CodeTypeTag.Enum && field.Type.EnumValues.Any(t => t.Item1 == field.Name)) { continue; } var userField = ExtractField(field, factory, generationFlags, forceIsStatic: true); if (field.Type.Tag == CodeTypeTag.Pointer) { // Do not use const values for pointers. // We do not allow user type implicit conversion from integers. userField.ConstantValue = string.Empty; } userField.FieldName = NormalizeSymbolNamespace(userField.FieldName); userField.PropertyName = NormalizeSymbolNamespace(userField.PropertyName); yield return(userField); usedNames.Add(field.PropertyName); } foreach (var field in GetAutoGeneratedFields(false, useThisClass)) { yield return(field); } }
/// <summary> /// Generates user type field based on the specified symbol field and all other fields that are prepared for this function. /// Do not use this function directly, unless you are calling it from overridden function. /// </summary> /// <param name="field">The symbol field.</param> /// <param name="fieldType">The field tree type.</param> /// <param name="factory">The user type factory.</param> /// <param name="simpleFieldValue">The code foe "simple field value" used when creating transformation.</param> /// <param name="gettingField">The code for getting field variable.</param> /// <param name="isStatic">if set to <c>true</c> generated field should be static.</param> /// <param name="generationFlags">The user type generation flags.</param> /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param> protected override UserTypeField ExtractFieldInternal(SymbolField field, TypeTree fieldType, UserTypeFactory factory, string simpleFieldValue, string gettingField, bool isStatic, UserTypeGenerationFlags generationFlags, bool extractingBaseClass) { // Physical code generation make sense only for non-static fields if (!isStatic) { bool lazyCacheUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.LazyCacheUserTypeFields); bool cacheUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.CacheUserTypeFields); bool cacheStaticUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.CacheStaticUserTypeFields); string constructorText = ""; string fieldName = field.Name; string fieldTypeString = fieldType.GetTypeString(); BasicTypeTree baseType = fieldType as BasicTypeTree; ArrayTypeTree codeArrayType = fieldType as ArrayTypeTree; UserTypeTree userType = fieldType as UserTypeTree; TransformationTypeTree transformationType = fieldType as TransformationTypeTree; bool isEmbedded = field.Type.Tag != CodeTypeTag.Pointer; // Specialization for basic types if (baseType != null) { if (baseType.BasicType == "string") { int charSize = field.Type.ElementType.Size; constructorText = string.Format("ReadString(GetCodeType().Module.Process, ReadPointer(memoryBuffer, memoryBufferOffset + {0}, {1}), {2})", field.Offset, field.Type.Size, charSize); } else if (baseType.BasicType != "NakedPointer") { if (field.LocationType == LocationType.BitField) { constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, field.Size, field.BitPosition); } else { constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1})", baseType.GetTypeString().UppercaseFirst(), field.Offset); } } } // Specialization for arrays else if (codeArrayType != null) { if (codeArrayType.ElementType is BasicTypeTree) { baseType = (BasicTypeTree)codeArrayType.ElementType; if (baseType != null && baseType.BasicType != "string" && baseType.BasicType != "NakedPointer") { int arraySize = field.Type.Size; int elementSize = field.Type.ElementType.Size; if (baseType.BasicType == "char") { constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize, elementSize); } else { constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize); } fieldTypeString = baseType.GetTypeString() + "[]"; } } } // Specialization for user types else if (userType != null && !extractingBaseClass) { if (!(userType.UserType is EnumUserType)) { string thisClassCodeType; if (IsTypeUsingStaticCodeType(this)) { thisClassCodeType = ClassCodeType; } else { thisClassCodeType = "thisClass.Value.GetCodeType()"; usedThisClass = true; } // Check if type is embedded if (!isEmbedded) { // If user type is not embedded, we do have pointer inside of our memory buffer that we can read directly if (IsTypeUsingStaticCodeType(this)) { constructorText = string.Format("ReadPointer<{0}>({4}, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size, ClassCodeType); } else { constructorText = string.Format("ReadPointer<{0}>(thisClass, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size); usedThisClass = true; } // Do downcasting if field has vtable if (userType.UserType.Symbol.HasVTable() && userType.UserType.DerivedClasses.Count > 0) { constructorText += ".DowncastObject()"; } } else { // If user type is embedded, we can reuse memory buffer that we already have in this class string fieldAddress = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset); string fieldCodeType = string.Format("{0}.GetClassFieldType(\"{1}\")", thisClassCodeType, fieldName); if (IsTypeUsingStaticCodeType(userType.UserType)) { fieldCodeType = string.Format("{0}.{1}", userType.UserType.FullClassName, ClassCodeType); } else if (IsTypeUsingStaticCodeType(this)) { fieldCodeType = AddFieldCodeType(fieldName); } constructorText = string.Format("new {0}(memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress, {2}, {3}, \"{4}\")", fieldTypeString, field.Offset, fieldCodeType, fieldAddress, fieldName); } } else { // TODO: This is enum. Read how much enum base type is big and just cast to enum type... } } // Specialization for transformations else if (transformationType != null) { if (!isEmbedded) { string thisClassCodeType; if (IsTypeUsingStaticCodeType(this)) { thisClassCodeType = ClassCodeType; } else { thisClassCodeType = "thisClass.Value.GetCodeType()"; usedThisClass = true; } string fieldAddress = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset); string fieldVariable = string.Format("Variable.CreateNoCast({0}.GetClassFieldType(\"{1}\"), {2}, \"{1}\")", thisClassCodeType, fieldName, fieldAddress); if (transformationType.Transformation.Transformation.HasPhysicalConstructor) { fieldVariable = string.Format("{0}, memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress", fieldVariable, field.Offset); } simpleFieldValue = fieldVariable; constructorText = string.Format("new {0}({1})", fieldTypeString, fieldVariable); } } // If we found suitable physical representation, generate the field if (!string.IsNullOrEmpty(constructorText)) { return new UserTypeField() { ConstructorText = constructorText, FieldName = "_" + fieldName, FieldType = fieldTypeString, FieldTypeInfoComment = string.Format("// {0} {1};", field.Type.Name, fieldName), PropertyName = UserTypeField.GetPropertyName(field, this), Static = isStatic, UseUserMember = lazyCacheUserTypeFields, CacheResult = cacheUserTypeFields || (isStatic && cacheStaticUserTypeFields), SimpleFieldValue = simpleFieldValue, } } ; } return(base.ExtractFieldInternal(field, fieldType, factory, simpleFieldValue, gettingField, isStatic, generationFlags, extractingBaseClass)); }