/// <summary> /// Generate a property to wrap the underlying bit vector /// </summary> /// <param name="ntMember"></param> /// <param name="offset"></param> /// <param name="ctd"></param> /// <param name="codeMember"></param> /// <remarks></remarks> private void GenerateBitVectorProperty(NativeMember ntMember, int offset, CodeTypeDeclaration ctd, CodeMemberField codeMember) { ThrowIfNull(ntMember); ThrowIfNull(ctd); ThrowIfNull(codeMember); ThrowIfTrue(offset < 0); NativeBitVector bitVector = null; IsBitVector(ntMember.NativeType, ref bitVector); // First calculate the bitmask uint mask = 0; for (int i = 0; i <= bitVector.Size - 1; i++) { mask <<= 1; mask = mask | 1u; } mask <<= offset; // Create the property CodeMemberProperty prop = new CodeMemberProperty(); prop.Name = ntMember.Name; prop.Attributes = MemberAttributes.Public | MemberAttributes.Final; prop.Type = new CodeTypeReference(typeof(uint)); ctd.Members.Add(prop); // Build the get and set GenerateBitVectorPropertyGet(prop, codeMember.Name, mask, offset, bitVector); GenerateBitVectorPropertySet(prop, codeMember.Name, mask, offset, bitVector); }
/// <summary> /// Generate the members of the container /// </summary> /// <param name="nt"></param> /// <param name="ctd"></param> /// <remarks></remarks> private void GenerateContainerMembers(NativeDefinedType nt, CodeTypeDeclaration ctd) { ThrowIfNull(nt); ThrowIfNull(ctd); int bitVectorCount = 0; for (int i = 0; i <= nt.Members.Count - 1; i++) { NativeMember member = nt.Members[i]; // Don't process unnamed container members if (string.IsNullOrEmpty(member.Name)) { continue; } if (IsBitVector(member.NativeType)) { // Get the list of bitvectors that will fit into the next int int bitCount = 0; List <NativeMember> list = new List <NativeMember>(); NativeBitVector bitVector = null; while ((i < nt.Members.Count && IsBitVector(nt.Members[i].NativeType, ref bitVector) && bitCount + bitVector.Size <= 32)) { list.Add(nt.Members[i]); i += 1; } i -= 1; // Generate the int for the list of bit vectors bitVectorCount += 1; CodeMemberField cMember = GenerateContainerMember(new NativeMember("bitvector" + bitVectorCount, new NativeBuiltinType(BuiltinType.NativeInt32, true)), ctd); cMember.Comments.Clear(); CodeComment comment = new CodeComment(string.Empty, true); int offset = 0; for (int j = 0; j <= list.Count - 1; j++) { if (j > 0) { comment.Text += Environment.NewLine; } IsBitVector(list[j].NativeType, ref bitVector); comment.Text += list[j].Name + " : " + bitVector.Size; GenerateBitVectorProperty(list[j], offset, ctd, cMember); offset += bitVector.Size; } cMember.Comments.Add(new CodeCommentStatement(comment)); } else { GenerateContainerMember(member, ctd); } } }
/// <summary> /// Top level takes a very shallow look at the type. When it encounters a nested defined type, it will only compare the /// name's. In that case NativeNamedType instances and NativeDefinedType instances will compare true if they match on name /// </summary> /// <param name="left"></param> /// <param name="right"></param> /// <returns></returns> /// <remarks></remarks> private bool EqualsTopLevel(NativeType left, NativeType right) { left = DigThroughNamedType(left); right = DigThroughNamedType(right); if (left.Kind != right.Kind) { return(false); } if (!EqualsCore(left, right)) { return(false); } // If this is a defined type then make sure the members compare if (left.Category == NativeSymbolCategory.Defined) { NativeDefinedType leftDefined = (NativeDefinedType)left; NativeDefinedType rightDefined = (NativeDefinedType)right; if (leftDefined.Members.Count != rightDefined.Members.Count) { return(false); } for (int i = 0; i <= leftDefined.Members.Count - 1; i++) { NativeMember leftMember = leftDefined.Members[i]; NativeMember rightMember = rightDefined.Members[i]; if (0 != string.CompareOrdinal(leftMember.Name, rightMember.Name) || !EqualsCore(leftMember.NativeType, rightMember.NativeType)) { return(false); } } } return(true); }
/// <summary> /// Generate the NativeMember /// </summary> /// <param name="nt"></param> /// <param name="ctd"></param> /// <remarks></remarks> private CodeMemberField GenerateContainerMember(NativeMember nt, CodeTypeDeclaration ctd) { ThrowIfNull(nt); ThrowIfNull(ctd); ThrowIfTrue(nt.NativeType.Kind == NativeSymbolKind.BitVectorType); // Bitvector instances should be handled seperately // Generate the type reference and comment string comment = string.Empty; CodeMemberField member = new CodeMemberField(); member.Name = nt.Name; member.Type = GenerateTypeReferenceImpl(nt.NativeType, ref comment); member.Attributes = MemberAttributes.Public; member.Comments.Add(new CodeCommentStatement(comment, true)); member.UserData.Add(TransformConstants.Member, nt); ctd.Members.Add(member); // If this is an array then add the appropriate marshal directive if it's an inline array NativeArray ntArray = nt.NativeType as NativeArray; if (ntArray != null && ntArray.ElementCount > 0) { // Add the struct layout attribute CodeTypeReference attrRef = new CodeTypeReference(typeof(MarshalAsAttribute)); CodeAttributeDeclaration attr = new CodeAttributeDeclaration(attrRef); // ByValArray CodeAttributeArgument asArg = new CodeAttributeArgument(); asArg.Name = string.Empty; asArg.Value = new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(UnmanagedType)), "ByValArray"); attr.Arguments.Add(asArg); // SizeConst arg CodeAttributeArgument sizeArg = new CodeAttributeArgument(); sizeArg.Name = "SizeConst"; sizeArg.Value = new CodePrimitiveExpression(ntArray.ElementCount); attr.Arguments.Add(sizeArg); // ArraySubType NativeType elemType = ntArray.RealTypeDigged; CodeAttributeArgument subTypeArg = new CodeAttributeArgument(); subTypeArg.Name = "ArraySubType"; if (elemType.Kind == NativeSymbolKind.BuiltinType) { // Builtin types know their size in bytes NativeBuiltinType elemBt = (NativeBuiltinType)elemType; subTypeArg.Value = new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(UnmanagedType)), elemBt.UnmanagedType.ToString()); } else if (elemType.Kind == NativeSymbolKind.PointerType || elemType.Kind == NativeSymbolKind.ArrayType) { // Marshal pointers as system ints subTypeArg.Value = new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(UnmanagedType)), "SysUInt"); } else { subTypeArg.Value = new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(UnmanagedType)), "Struct"); } attr.Arguments.Add(subTypeArg); member.CustomAttributes.Add(attr); } return(member); }