private void Validate(NamingRules value, NamingRules option1, NamingRules option2)
 {
     if ((value & option1) == option1 && (value & option2) == option2)
     {
         throw new ArgumentException(string.Format(Strings.ExOptionXIsMutuallyExclusiveWithOptionY, option1, option2));
     }
 }
        private Domain BuildDomain(DomainUpgradeMode upgradeMode, NamingRules namingRules, Type sampleType)
        {
            var configuration = DomainConfigurationFactory.Create();

            configuration.UpgradeMode = upgradeMode;
            configuration.NamingConvention.NamingRules = namingRules;
            configuration.Types.Register(sampleType.Assembly, sampleType.Namespace);
            return(Domain.Build(configuration));
        }
Ejemplo n.º 3
0
 private void UpdateNamingRules(ConfigFile file)
 {
     foreach (var namingRule in file.Naming)
     {
         if (namingRule is NamingRuleShort)
         {
             NamingRules.AddShortNameRule(namingRule.Name, namingRule.Value);
         }
     }
 }
Ejemplo n.º 4
0
        /// <summary>
        /// Adds a list of constant gathered from macros/guids to a C# type.
        /// </summary>
        /// <param name="elementFinder">The C++ module to search.</param>
        /// <param name="macroRegexp">The macro regexp.</param>
        /// <param name="fullNameCSharpType">Full type of the name C sharp.</param>
        /// <param name="type">The type.</param>
        /// <param name="fieldName">Name of the field.</param>
        /// <param name="valueMap">The value map.</param>
        /// <param name="visibility">The visibility.</param>
        /// <param name="nameSpace">The current namespace.</param>
        public void AddConstantFromMacroToCSharpType(CppElementFinder elementFinder, string macroRegexp, string fullNameCSharpType, string type, string fieldName, string valueMap,
                                                     Visibility?visibility, string nameSpace)
        {
            var constantDefinitions = elementFinder.Find <CppConstant>(macroRegexp);
            var regex = new Regex(macroRegexp);

            // $0: Name of the C++ macro
            // $1: Value of the C++ macro
            // $2: Name of the C#
            // $3: Name of current namespace
            if (valueMap != null)
            {
                valueMap = valueMap.Replace("{", "{{");
                valueMap = valueMap.Replace("}", "}}");
                valueMap = valueMap.Replace("$0", "{0}");
                valueMap = valueMap.Replace("$1", "{1}");
                valueMap = valueMap.Replace("$2", "{2}");
                valueMap = valueMap.Replace("$3", "{3}");
            }

            foreach (var macroDef in constantDefinitions)
            {
                var finalFieldName = fieldName == null ?
                                     macroDef.Name
                    : NamingRules.ConvertToPascalCase(
                    regex.Replace(macroDef.Name, fieldName),
                    NamingFlags.Default);
                var finalValue = valueMap == null ?
                                 macroDef.Value
                    : string.Format(valueMap, macroDef.Name, macroDef.Value, finalFieldName, nameSpace);

                var constant = AddConstantToCSharpType(macroDef, fullNameCSharpType, type, finalFieldName, finalValue);
                constant.Visibility = visibility ?? Visibility.Public | Visibility.Const;
            }

            var guidDefinitions = elementFinder.Find <CppGuid>(macroRegexp);

            foreach (var guidDef in guidDefinitions)
            {
                var finalFieldName = fieldName == null ?
                                     guidDef.Name
                    : NamingRules.ConvertToPascalCase(
                    regex.Replace(guidDef.Name, fieldName),
                    NamingFlags.Default);
                var finalValue = valueMap == null?
                                 guidDef.Guid.ToString()
                                     : string.Format(valueMap, guidDef.Name, guidDef.Guid.ToString(), finalFieldName, nameSpace);

                var constant = AddConstantToCSharpType(guidDef, fullNameCSharpType, type, finalFieldName, finalValue);
                constant.Visibility = visibility ?? Visibility.Public | Visibility.Static | Visibility.Readonly;
            }
        }
Ejemplo n.º 5
0
        public void DotsAndHypensExclusiveOptionsTest()
        {
            var configuration = new DomainConfiguration();

            const NamingRules invalidRules1 = NamingRules.UnderscoreDots | NamingRules.UnderscoreHyphens | NamingRules.RemoveDots;
            const NamingRules invalidRules2 = NamingRules.RemoveDots | NamingRules.RemoveHyphens | NamingRules.UnderscoreHyphens;
            const NamingRules validRules1   = NamingRules.UnderscoreHyphens | NamingRules.UnderscoreDots;
            const NamingRules validRules2   = NamingRules.RemoveDots | NamingRules.RemoveHyphens;

            var convention = configuration.NamingConvention;

            AssertEx.ThrowsArgumentException(() => convention.NamingRules = invalidRules1);
            AssertEx.ThrowsArgumentException(() => convention.NamingRules = invalidRules2);

            convention.NamingRules = validRules1;
            convention.NamingRules = validRules2;
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Prepares C++ struct for mapping. This method is creating the associated C# struct.
        /// </summary>
        /// <param name="cppStruct">The c++ struct.</param>
        /// <returns></returns>
        public override CsStruct Prepare(CppStruct cppStruct)
        {
            // Create a new C# struct
            var nameSpace = namespaceRegistry.ResolveNamespace(cppStruct);
            var csStruct  = new CsStruct(cppStruct)
            {
                Name = NamingRules.Rename(cppStruct),
                // IsFullyMapped to false => The structure is being mapped
                IsFullyMapped = false
            };

            // Add the C# struct to its namespace
            nameSpace.Add(csStruct);

            // Map the C++ name to the C# struct
            typeRegistry.BindType(cppStruct.Name, csStruct);
            return(csStruct);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Prepares the specified C++ element to a C# element.
        /// </summary>
        /// <param name="cppElement">The C++ element.</param>
        /// <returns>The C# element created and registered to the <see cref="TransformManager"/></returns>
        public override CsBase Prepare(CppElement cppElement)
        {
            var cppInterface = (CppInterface)cppElement;

            // IsFullyMapped to false => The structure is being mapped
            var cSharpInterface = new CsInterface(cppInterface)
            {
                IsFullyMapped = false
            };
            CsNamespace nameSpace = Manager.ResolveNamespace(cppInterface);

            cSharpInterface.Name = NamingRules.Rename(cppInterface);
            nameSpace.Add(cSharpInterface);

            Manager.BindType(cppInterface.Name, cSharpInterface);

            return(cSharpInterface);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Processes the specified method.
        /// </summary>
        /// <param name="method">The method.</param>
        private void ProcessMethod(CsCallable method)
        {
            var cppMethod = (CppCallable)method.CppElement;

            method.Name = NamingRules.Rename(cppMethod);

            // For methods, the tag "type" is only used for return type
            // So we are overriding the return type here
            var methodRule = cppMethod.GetMappingRule();

            if (methodRule.MappingType != null)
            {
                cppMethod.ReturnValue.Rule = new MappingRule {
                    MappingType = methodRule.MappingType
                }
            }
            ;

            // Get the inferred return type
            method.ReturnValue = factory.Create(cppMethod.ReturnValue);

            if (method.ReturnValue.PublicType is CsInterface iface && iface.IsCallback)
            {
                method.ReturnValue.PublicType = iface.GetNativeImplementationOrThis();
            }

            // Hide return type only if it is a HRESULT and AlwaysReturnHResult is false
            if (method.CheckReturnType && method.ReturnValue.PublicType != null &&
                method.ReturnValue.PublicType.QualifiedName == globalNamespace.GetTypeName(WellKnownName.Result))
            {
                method.HideReturnType = !method.AlwaysReturnHResult;
            }

            // Iterates on parameters to convert them to C# parameters
            foreach (var cppParameter in cppMethod.Parameters)
            {
                var paramMethod = factory.Create(cppParameter);

                paramMethod.Name = NamingRules.Rename(cppParameter);

                method.Add(paramMethod);
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Prepares the specified C++ element to a C# element.
        /// </summary>
        /// <param name="cppEnum">The C++ element.</param>
        /// <returns>The C# element created and registered to the <see cref="TransformManager"/></returns>
        public override CsEnum Prepare(CppEnum cppEnum)
        {
            // Create C# enum
            var newEnum = new CsEnum
            {
                Name           = NamingRules.Rename(cppEnum),
                CppElement     = cppEnum,
                UnderlyingType = typeRegistry.ImportType(typeof(int))
            };

            // Get the namespace for this particular include and enum
            var nameSpace = namespaceRegistry.ResolveNamespace(cppEnum);

            nameSpace.Add(newEnum);

            // Bind C++ enum to C# enum
            typeRegistry.BindType(cppEnum.Name, newEnum);

            return(newEnum);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Prepares C++ struct for mapping. This method is creating the associated C# struct.
        /// </summary>
        /// <param name="cppElement">The c++ struct.</param>
        /// <returns></returns>
        public override CsBase Prepare(CppElement cppElement)
        {
            var cppStruct = (CppStruct)cppElement;

            // Create a new C# struct
            var nameSpace = Manager.ResolveNamespace(cppStruct);
            var csStruct  = new CsStruct(cppStruct)
            {
                Name = NamingRules.Rename(cppStruct),
                // IsFullyMapped to false => The structure is being mapped
                IsFullyMapped = false
            };

            // Add the C# struct to its namespace
            nameSpace.Add(csStruct);

            // Map the C++ name to the C# struct
            Manager.BindType(cppStruct.Name, csStruct);
            return(csStruct);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Prepares the specified C++ element to a C# element.
        /// </summary>
        /// <param name="cppInterface">The C++ element.</param>
        /// <returns>The C# element created and registered to the <see cref="TransformManager"/></returns>
        public override CsInterface Prepare(CppInterface cppInterface)
        {
            // IsFullyMapped to false => The structure is being mapped
            var cSharpInterface = new CsInterface(cppInterface)
            {
                IsFullyMapped = false
            };
            var nameSpace = namespaceRegistry.ResolveNamespace(cppInterface);

            cSharpInterface.Name = NamingRules.Rename(cppInterface);
            nameSpace.Add(cSharpInterface);

            typeRegistry.BindType(cppInterface.Name, cSharpInterface);

            foreach (var cppMethod in cppInterface.Methods)
            {
                cSharpInterface.Add(MethodPreparer.Prepare(cppMethod));
            }

            return(cSharpInterface);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Prepares the specified C++ element to a C# element.
        /// </summary>
        /// <param name="cppElement">The C++ element.</param>
        /// <returns>The C# element created and registered to the <see cref="TransformManager"/></returns>
        public override CsBase Prepare(CppElement cppElement)
        {
            var cppEnum = (CppEnum)cppElement;

            // Create C# enum
            var newEnum = new CsEnum
            {
                Name       = NamingRules.Rename(cppEnum),
                CppElement = cppEnum
            };

            // Get the namespace for this particular include and enum
            var nameSpace = Manager.ResolveNamespace(cppEnum);

            nameSpace.Add(newEnum);

            // Bind C++ enum to C# enum
            Manager.BindType(cppEnum.Name, newEnum);

            return(newEnum);
        }
Ejemplo n.º 13
0
        private void BuildDomain(string version, DomainUpgradeMode upgradeMode, NamingRules namingRules)
        {
            if (domain != null)
            {
                domain.DisposeSafely();
            }

            string ns       = typeof(M1.Person).Namespace;
            string nsPrefix = ns.Substring(0, ns.Length - 1);

            var configuration = DomainConfigurationFactory.Create();

            configuration.UpgradeMode = upgradeMode;
            configuration.Types.Register(Assembly.GetExecutingAssembly(), nsPrefix + version);
            configuration.Types.Register(typeof(Upgrader));
            configuration.NamingConvention.NamingRules = namingRules;

            using (Upgrader.Enable(version)) {
                domain = Domain.Build(configuration);
            }
        }
        private void RunTest(NamingRules namingRules)
        {
            int myEntityTypeId;
            int myChildEntityTypeId;

            using (var domain = BuildInitialDomain(namingRules))
                using (var session = domain.OpenSession())
                    using (var tx = session.OpenTransaction()) {
                        var types = domain.Model.Types;
                        myEntityTypeId      = types[typeof(MyEntity)].TypeId;
                        myChildEntityTypeId = types[typeof(V1.MyChildEntity)].TypeId;

                        new MyEntity();
                        new V1.MyChildEntity();

                        tx.Complete();
                    }

            using (var domain = BuildUpgradedDomain(namingRules))
                using (var session = domain.OpenSession())
                    using (var tx = session.OpenTransaction()) {
                        var types = domain.Model.Types;
                        Assert.That(types[typeof(MyEntity)].TypeId, Is.EqualTo(myEntityTypeId));
                        Assert.That(types[typeof(V2.MyChildEntity)].TypeId, Is.EqualTo(myChildEntityTypeId));

                        var allItems = session.Query.All <MyEntity>().ToList();
                        Assert.That(allItems.Count, Is.EqualTo(2));
                        Assert.That(allItems.Count(item => item is V2.MyChildEntity), Is.EqualTo(1));
                        Assert.That(allItems.Count(item => !(item is V2.MyChildEntity)), Is.EqualTo(1));

                        var myChildEntity = session.Query.All <V2.MyChildEntity>().Single();
                        Assert.That(myChildEntity.Name, Is.EqualTo("MyChildEntity"));

                        var myEntity = session.Query.All <MyEntity>().Single(e => e != myChildEntity);
                        Assert.That(myEntity.Name, Is.EqualTo("MyEntity"));

                        tx.Complete();
                    }
        }
Ejemplo n.º 15
0
 private void RunTest(NamingRules namingRules)
 {
     BuildDomain("1", DomainUpgradeMode.Recreate, namingRules);
     using (var session = domain.OpenSession()) {
         using (var tx = session.OpenTransaction()) {
             var person = new M1.Person {
                 Name   = "Vasya",
                 Weight = 80,
                 Age    = 20,
                 Phone  = new M1.Phone(),
             };
             tx.Complete();
         }
     }
     BuildDomain("2", DomainUpgradeMode.PerformSafely, namingRules);
     using (var session = domain.OpenSession()) {
         using (var tx = session.OpenTransaction()) {
             var vasya = session.Query.All <Model.Version2.Person>().Single();
             Assert.AreEqual("Vasya", vasya.Name);
             Assert.AreEqual(80, vasya.Weight);
             Assert.IsNotNull(vasya.Phone);
         }
     }
 }
 private Task <Domain> BuildUpgradedDomainAsync(NamingRules namingRules) =>
 BuildDomainAsync(DomainUpgradeMode.PerformSafely, namingRules, typeof(V2.MyChildEntity));
Ejemplo n.º 17
0
        /// <summary>
        /// Processes the specified method.
        /// </summary>
        /// <param name="method">The method.</param>
        private void Process(CsMethod method)
        {
            var cppMethod = (CppMethod)method.CppElement;

            method.Name   = NamingRules.Rename(cppMethod);
            method.Offset = cppMethod.Offset;

            // For methods, the tag "type" is only used for return type
            // So we are overriding the return type here
            var tag = cppMethod.GetTagOrDefault <MappingRule>();

            if (tag.MappingType != null)
            {
                cppMethod.ReturnType.Tag = new MappingRule {
                    MappingType = tag.MappingType
                }
            }
            ;

            // Apply any offset to the method's vtable
            method.Offset += tag.LayoutOffsetTranslate;

            // Get the inferred return type
            method.ReturnType = Manager.GetCsType <CsMarshalBase>(cppMethod.ReturnType);

            // Hide return type only if it is a HRESULT and AlwaysReturnHResult is false
            if (method.CheckReturnType && method.ReturnType.PublicType != null &&
                method.ReturnType.PublicType.QualifiedName == Manager.GlobalNamespace.GetTypeName("Result"))
            {
                method.HideReturnType = !method.AlwaysReturnHResult;
            }

            // Iterates on parameters to convert them to C# parameters
            foreach (var cppParameter in cppMethod.Parameters)
            {
                var cppAttribute = cppParameter.Attribute;
                var paramTag     = cppParameter.GetTagOrDefault <MappingRule>();

                bool hasArray   = cppParameter.IsArray || ((cppAttribute & ParamAttribute.Buffer) != 0);
                bool hasParams  = (cppAttribute & ParamAttribute.Params) == ParamAttribute.Params;
                bool isOptional = (cppAttribute & ParamAttribute.Optional) != 0;

                var paramMethod = Manager.GetCsType <CsParameter>(cppParameter);

                paramMethod.Name = NamingRules.Rename(cppParameter);

                bool hasPointer = paramMethod.HasPointer;

                var publicType  = paramMethod.PublicType;
                var marshalType = paramMethod.MarshalType;

                CsParameterAttribute parameterAttribute = CsParameterAttribute.In;

                if (hasArray)
                {
                    hasPointer = true;
                }

                // --------------------------------------------------------------------------------
                // Pointer - Handle special cases
                // --------------------------------------------------------------------------------
                if (hasPointer)
                {
                    marshalType = Manager.ImportType(typeof(IntPtr));

                    // --------------------------------------------------------------------------------
                    // Handling Parameter Interface
                    // --------------------------------------------------------------------------------
                    if (publicType is CsInterface)
                    {
                        // Force Interface** to be ParamAttribute.Out when None
                        if (cppAttribute == ParamAttribute.In)
                        {
                            if (cppParameter.Pointer == "**")
                            {
                                cppAttribute = ParamAttribute.Out;
                            }
                        }

                        if ((cppAttribute & ParamAttribute.In) != 0 || (cppAttribute & ParamAttribute.InOut) != 0)
                        {
                            parameterAttribute = CsParameterAttribute.In;

                            // Force all array of interface to support null
                            if (hasArray)
                            {
                                isOptional = true;
                            }

                            // If Interface is a callback, use IntPtr as a public marshalling type
                            CsInterface publicCsInterface = (CsInterface)publicType;
                            if (publicCsInterface.IsCallback)
                            {
                                publicType = Manager.ImportType(typeof(IntPtr));
                                // By default, set the Visibility to internal for methods using callbacks
                                // as we need to provide user method. Don't do this on functions as they
                                // are already hidden by the container
                                if (!(method is CsFunction))
                                {
                                    method.Visibility = Visibility.Internal;
                                    method.Name       = method.Name + "_";
                                }
                            }
                        }
                        //else if ((cppParameter.Attribute & ParamAttribute.InOut) != 0)
                        //    parameterAttribute = method.ParameterAttribute.Ref;
                        else if ((cppAttribute & ParamAttribute.Out) != 0)
                        {
                            parameterAttribute = CsParameterAttribute.Out;
                        }
                    }
                    else
                    {
                        // If a pointer to array of bool are handle as array of int
                        if (paramMethod.IsBoolToInt && (cppAttribute & ParamAttribute.Buffer) != 0)
                        {
                            publicType = Manager.ImportType(typeof(int));
                        }

                        // --------------------------------------------------------------------------------
                        // Handling Parameter Interface
                        // --------------------------------------------------------------------------------


                        if ((cppAttribute & ParamAttribute.In) != 0)
                        {
                            parameterAttribute = publicType.Type == typeof(IntPtr) || publicType.Name == Manager.GlobalNamespace.GetTypeName("FunctionCallback") ||
                                                 publicType.Type == typeof(string)
                                                     ? CsParameterAttribute.In
                                                     : CsParameterAttribute.RefIn;
                        }
                        else if ((cppAttribute & ParamAttribute.InOut) != 0)
                        {
                            if ((cppAttribute & ParamAttribute.Optional) != 0)
                            {
                                publicType         = Manager.ImportType(typeof(IntPtr));
                                parameterAttribute = CsParameterAttribute.In;
                            }
                            else
                            {
                                parameterAttribute = CsParameterAttribute.Ref;
                            }
                        }
                        else if ((cppAttribute & ParamAttribute.Out) != 0)
                        {
                            parameterAttribute = CsParameterAttribute.Out;
                        }

                        // Handle void* with Buffer attribute
                        if (cppParameter.TypeName == "void" && (cppAttribute & ParamAttribute.Buffer) != 0)
                        {
                            hasArray           = false;
                            parameterAttribute = CsParameterAttribute.In;
                        }
                        else if (publicType.Type == typeof(string) && (cppAttribute & ParamAttribute.Out) != 0)
                        {
                            publicType         = Manager.ImportType(typeof(IntPtr));
                            parameterAttribute = CsParameterAttribute.In;
                            hasArray           = false;
                        }
                        else if (publicType is CsStruct &&
                                 (parameterAttribute == CsParameterAttribute.Out || hasArray || parameterAttribute == CsParameterAttribute.RefIn || parameterAttribute == CsParameterAttribute.Ref))
                        {
                            // Set IsOut on structure to generate proper marshalling
                            (publicType as CsStruct).IsOut = true;
                        }
                    }
                }

                paramMethod.HasPointer  = hasPointer;
                paramMethod.Attribute   = parameterAttribute;
                paramMethod.IsArray     = hasArray;
                paramMethod.HasParams   = hasParams;
                paramMethod.HasPointer  = hasPointer;
                paramMethod.PublicType  = publicType ?? throw new ArgumentException("Public type cannot be null");
                paramMethod.MarshalType = marshalType;
                paramMethod.IsOptional  = isOptional;

                // Force IsString to be only string (due to Buffer attribute)
                if (paramMethod.IsString)
                {
                    paramMethod.IsArray = false;
                }

                method.Add(paramMethod);
            }
        }
    }
Ejemplo n.º 18
0
        /// <summary>
        /// Maps the C++ struct to C# struct.
        /// </summary>
        /// <param name="csStruct">The c sharp struct.</param>
        private void Process(CsStruct csStruct)
        {
            // TODO: this mapping must be robust. Current calculation for field offset is not always accurate for union.
            // TODO: need to handle align/packing correctly.

            // If a struct was already mapped, then return immediately
            // The method MapStruct can be called recursively
            if (csStruct.IsFullyMapped)
            {
                return;
            }

            // Set IsFullyMappy in order to avoid recursive mapping
            csStruct.IsFullyMapped = true;

            // Get the associated CppStruct and CSharpTag
            var  cppStruct      = (CppStruct)csStruct.CppElement;
            bool hasMarshalType = csStruct.HasMarshalType;

            // If this structure need to me moved to another container, move it now
            foreach (var keyValuePair in _mapMoveStructToInner)
            {
                if (keyValuePair.Key.Match(csStruct.CppElementName).Success)
                {
                    string cppName         = keyValuePair.Key.Replace(csStruct.CppElementName, keyValuePair.Value);
                    var    destSharpStruct = (CsStruct)Manager.FindBindType(cppName);
                    // Remove the struct from his container
                    csStruct.Parent.Remove(csStruct);
                    // Add this struct to the new container struct
                    destSharpStruct.Add(csStruct);
                }
            }

            // Current offset of a field
            int currentFieldAbsoluteOffset = 0;

            // Last field offset
            int previousFieldOffsetIndex = -1;

            // Size of the last field
            int previousFieldSize = 0;

            //
            int maxSizeOfField = 0;

            bool isInUnion = false;

            int cumulatedBitOffset = 0;


            var inheritedStructs = new Stack <CppStruct>();
            var currentStruct    = cppStruct;

            while (currentStruct != null && currentStruct.ParentName != currentStruct.Name)
            {
                inheritedStructs.Push(currentStruct);
                currentStruct = Manager.FindBindType(currentStruct.ParentName)?.CppElement as CppStruct;
            }

            while (inheritedStructs.Count > 0)
            {
                currentStruct = inheritedStructs.Pop();

                int fieldCount = currentStruct.IsEmpty ? 0 : currentStruct.Items.Count;

                // -------------------------------------------------------------------------------
                // Iterate on all fields and perform mapping
                // -------------------------------------------------------------------------------
                for (int fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++)
                {
                    var cppField = (CppField)currentStruct.Items[fieldIndex];
                    Logger.RunInContext(cppField.ToString(), () =>
                    {
                        var fieldStruct = Manager.GetCsType <CsField>(cppField, true);
                        csStruct.Add(fieldStruct);

                        // Get name
                        fieldStruct.Name = NamingRules.Rename(cppField);

                        // BoolToInt doesn't generate native Marshaling although they have a different marshaller
                        if (!fieldStruct.IsBoolToInt && fieldStruct.HasMarshalType)
                        {
                            hasMarshalType = true;
                        }


                        // If last field has same offset, then it's a union
                        // CurrentOffset is not moved
                        if (isInUnion && previousFieldOffsetIndex != cppField.Offset)
                        {
                            previousFieldSize = maxSizeOfField;
                            maxSizeOfField    = 0;
                            isInUnion         = false;
                        }

                        currentFieldAbsoluteOffset += previousFieldSize;
                        var fieldAlignment          = (fieldStruct.MarshalType ?? fieldStruct.PublicType).CalculateAlignment();

                        // If field alignment is < 0, then we have a pointer somewhere so we can't align
                        if (fieldAlignment > 0)
                        {
                            // otherwise, align the field on the alignment requirement of the field
                            int delta = (currentFieldAbsoluteOffset % fieldAlignment);
                            if (delta != 0)
                            {
                                currentFieldAbsoluteOffset += fieldAlignment - delta;
                            }
                        }

                        // Get correct offset (for handling union)
                        fieldStruct.Offset     = currentFieldAbsoluteOffset;
                        fieldStruct.IsBitField = cppField.IsBitField;

                        // Handle bit fields : calculate BitOffset and BitMask for this field
                        if (previousFieldOffsetIndex != cppField.Offset)
                        {
                            cumulatedBitOffset = 0;
                        }
                        if (cppField.IsBitField)
                        {
                            int lastCumulatedBitOffset = cumulatedBitOffset;
                            cumulatedBitOffset        += cppField.BitOffset;
                            fieldStruct.BitMask        = ((1 << cppField.BitOffset) - 1); // &~((1 << (lastCumulatedBitOffset + 1)) - 1);
                            fieldStruct.BitOffset      = lastCumulatedBitOffset;
                        }


                        var nextFieldIndex = fieldIndex + 1;
                        if ((previousFieldOffsetIndex == cppField.Offset) ||
                            (nextFieldIndex < fieldCount && ((CppField)currentStruct.Items[nextFieldIndex]).Offset == cppField.Offset))
                        {
                            if (previousFieldOffsetIndex != cppField.Offset)
                            {
                                maxSizeOfField = 0;
                            }
                            maxSizeOfField          = fieldStruct.SizeOf > maxSizeOfField ? fieldStruct.SizeOf : maxSizeOfField;
                            isInUnion               = true;
                            csStruct.ExplicitLayout = true;
                            previousFieldSize       = 0;
                        }
                        else
                        {
                            previousFieldSize = fieldStruct.SizeOf;
                        }
                        previousFieldOffsetIndex = cppField.Offset;
                    });
                }
            }

            // In case of explicit layout, check that we can safely generate it on both x86 and x64 (in case of an union
            // using pointers, we can't)
            if (csStruct.ExplicitLayout)
            {
                var fieldList = csStruct.Fields.ToList();
                for (int i = 0; i < fieldList.Count; i++)
                {
                    var field          = fieldList[i];
                    var fieldAlignment = (field.MarshalType ?? field.PublicType).CalculateAlignment();

                    if (fieldAlignment < 0)
                    {
                        // If pointer field is not the last one, than we can't handle it
                        if ((i + 1) < fieldList.Count)
                        {
                            Logger.Error(
                                "The field [{0}] in structure [{1}] has pointer alignment within a structure that contains an union. An explicit layout cannot be handled on both x86/x64. This structure needs manual layout (remove fields from definition) and write them manually in xml mapping files",
                                field.CppElementName,
                                csStruct.CppElementName);
                            break;
                        }
                    }
                }
            }

            csStruct.SizeOf         = currentFieldAbsoluteOffset + previousFieldSize;
            csStruct.HasMarshalType = hasMarshalType;
        }
        private Task <Domain> BuildDomainAsync(DomainUpgradeMode upgradeMode, NamingRules namingRules, Type sampleType)
        {
            var configuration = BuildDomainConfiguration(upgradeMode, namingRules, sampleType);

            return(Domain.BuildAsync(configuration));
        }
 private Domain BuildInitialDomain(NamingRules namingRules) =>
 BuildDomain(DomainUpgradeMode.Recreate, namingRules, typeof(V1.MyChildEntity));
Ejemplo n.º 21
0
        /// <summary>
        /// Maps the C++ struct to C# struct.
        /// </summary>
        /// <param name="csStruct">The c sharp struct.</param>
        private void Process(CsStruct csStruct)
        {
            // TODO: this mapping must be robust. Current caculation for field offset is not always accurate for union.
            // TODO: need to handle align/packing correctly.

            // If a struct was already mapped, then return immediatly
            // The method MapStruct can be called recursivelly
            if (csStruct.IsFullyMapped)
            {
                return;
            }

            // Set IsFullyMappy in order to avoid recursive mapping
            csStruct.IsFullyMapped = true;

            // Get the associated CppStruct and CSharpTag
            var  cppStruct      = (CppStruct)csStruct.CppElement;
            bool hasMarshalType = csStruct.HasMarshalType;

            // If this structure need to me moved to anoter container, move it now
            foreach (var keyValuePair in _mapMoveStructToInner)
            {
                if (keyValuePair.Key.Match(csStruct.CppElementName).Success)
                {
                    string cppName         = keyValuePair.Key.Replace(csStruct.CppElementName, keyValuePair.Value);
                    var    destSharpStruct = (CsStruct)Manager.FindBindType(cppName);
                    // Remove the struct from his container
                    csStruct.Parent.Remove(csStruct);
                    // Add this struct to the new container struct
                    destSharpStruct.Add(csStruct);
                }
            }

            // Current offset of a field
            int currentOffset = 0;

            int fieldCount = cppStruct.IsEmpty ? 0 : cppStruct.Items.Count;


            // Offset stored for each field
            int[] offsetOfFields = new int[fieldCount];

            // Last field offset
            int lastCppFieldOffset = -1;

            // Size of the last field
            int lastFieldSize = 0;

            //
            int maxSizeOfField = 0;

            bool isInUnion = false;

            int cumulatedBitOffset = 0;

            // -------------------------------------------------------------------------------
            // Iterate on all fields and perform mapping
            // -------------------------------------------------------------------------------
            for (int fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++)
            {
                var cppField = (CppField)cppStruct.Items[fieldIndex];
                Logger.RunInContext(cppField.ToString(), () =>
                {
                    var fieldStruct = Manager.GetCsType <CsField>(cppField, true);

                    // Get name
                    fieldStruct.Name = NamingRules.Rename(cppField);

                    // BoolToInt doesn't generate native Marshaling although they have a different marshaller
                    if (!fieldStruct.IsBoolToInt && fieldStruct.HasMarshalType)
                    {
                        hasMarshalType = true;
                    }

                    // If last field has same offset, then it's a union
                    // CurrentOffset is not moved
                    if (isInUnion && lastCppFieldOffset != cppField.Offset)
                    {
                        lastFieldSize  = maxSizeOfField;
                        maxSizeOfField = 0;
                        isInUnion      = false;
                    }

                    currentOffset += lastFieldSize;
                    offsetOfFields[cppField.Offset] = currentOffset;
                    // Get correct offset (for handling union)
                    fieldStruct.Offset     = offsetOfFields[cppField.Offset];
                    fieldStruct.IsBitField = cppField.IsBitField;

                    // Handle bit fields : calculate BitOffset and BitMask for this field
                    if (lastCppFieldOffset != cppField.Offset)
                    {
                        cumulatedBitOffset = 0;
                    }
                    if (cppField.IsBitField)
                    {
                        int lastCumulatedBitOffset = cumulatedBitOffset;
                        cumulatedBitOffset        += cppField.BitOffset;
                        fieldStruct.BitMask        = ((1 << cppField.BitOffset) - 1); // &~((1 << (lastCumulatedBitOffset + 1)) - 1);
                        //fieldStruct.BitMask2 = ((1 << cppField.BitOffset) - 1); // &~((1 << (lastCumulatedBitOffset + 1)) - 1);
                        fieldStruct.BitOffset = lastCumulatedBitOffset;
                    }
                    csStruct.Add(fieldStruct);
                    // TODO : handle packing rules here!!!!!

                    // If last field has same offset, then it's a union
                    // CurrentOffset is not moved
                    if (lastCppFieldOffset == cppField.Offset ||
                        ((fieldIndex + 1) < fieldCount &&
                         (cppStruct.Items[fieldIndex + 1] as CppField).Offset == cppField.Offset))
                    {
                        isInUnion = true;
                        csStruct.ExplicitLayout = true;
                        maxSizeOfField          = fieldStruct.SizeOf > maxSizeOfField ? fieldStruct.SizeOf : maxSizeOfField;
                        lastFieldSize           = 0;
                    }
                    else
                    {
                        lastFieldSize = fieldStruct.SizeOf;
                    }
                    lastCppFieldOffset = cppField.Offset;
                });
            }
            csStruct.SizeOf         = currentOffset + lastFieldSize;
            csStruct.HasMarshalType = hasMarshalType;
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Maps the C++ struct to C# struct.
        /// </summary>
        /// <param name="csStruct">The c sharp struct.</param>
        public override void Process(CsStruct csStruct)
        {
            // TODO: this mapping must be robust. Current calculation for field offset is not always accurate for union.
            // TODO: need to handle align/packing correctly.

            // If a struct was already mapped, then return immediately
            // The method MapStruct can be called recursively
            if (csStruct.IsFullyMapped)
            {
                return;
            }

            // Set IsFullyMappy in order to avoid recursive mapping
            csStruct.IsFullyMapped = true;

            // Get the associated CppStruct and CSharpTag
            var  cppStruct      = (CppStruct)csStruct.CppElement;
            bool hasMarshalType = csStruct.HasMarshalType;

            // If this structure need to me moved to another container, move it now
            foreach (var keyValuePair in _mapMoveStructToInner)
            {
                if (keyValuePair.Key.Match(csStruct.CppElementName).Success)
                {
                    string cppName         = keyValuePair.Key.Replace(csStruct.CppElementName, keyValuePair.Value);
                    var    destSharpStruct = (CsStruct)typeRegistry.FindBoundType(cppName);
                    // Remove the struct from his container
                    csStruct.Parent.Remove(csStruct);
                    // Add this struct to the new container struct
                    destSharpStruct.Add(csStruct);
                }
            }

            // Current offset of a field
            int currentFieldAbsoluteOffset = 0;

            // Last field offset
            int previousFieldOffsetIndex = -1;

            // Size of the last field
            int previousFieldSize = 0;

            //
            int maxSizeOfField = 0;

            bool isNonSequential = false;

            int cumulatedBitOffset = 0;

            var inheritedStructs = new Stack <CppStruct>();
            var currentStruct    = cppStruct;

            while (currentStruct != null && currentStruct.Base != currentStruct.Name)
            {
                inheritedStructs.Push(currentStruct);
                currentStruct = typeRegistry.FindBoundType(currentStruct.Base)?.CppElement as CppStruct;
            }

            while (inheritedStructs.Count > 0)
            {
                currentStruct = inheritedStructs.Pop();

                int fieldCount = currentStruct.IsEmpty ? 0 : currentStruct.Items.Count;

                // -------------------------------------------------------------------------------
                // Iterate on all fields and perform mapping
                // -------------------------------------------------------------------------------
                for (int fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++)
                {
                    var cppField = (CppField)currentStruct.Items[fieldIndex];
                    Logger.RunInContext(cppField.ToString(), () =>
                    {
                        var csField = factory.Create(cppField);
                        csStruct.Add(csField);

                        // Get name
                        csField.Name = NamingRules.Rename(cppField);

                        var fieldHasMarshalType = csField.PublicType != csField.MarshalType ||
                                                  (csField.PublicType is CsStruct fieldStruct && fieldStruct.HasMarshalType) ||
                                                  csField.IsArray;

                        // BoolToInt doesn't generate native Marshaling although they have a different marshaller
                        if (((!csField.IsBoolToInt || csField.IsArray) && fieldHasMarshalType) || csField.Relation != null)
                        {
                            hasMarshalType = true;
                        }

                        // If last field has same offset, then it's a union
                        // CurrentOffset is not moved
                        if (isNonSequential && previousFieldOffsetIndex != cppField.Offset)
                        {
                            previousFieldSize = maxSizeOfField;
                            maxSizeOfField    = 0;
                            isNonSequential   = false;
                        }

                        currentFieldAbsoluteOffset += previousFieldSize;
                        var fieldAlignment          = (csField.MarshalType ?? csField.PublicType).CalculateAlignment();

                        // If field alignment is < 0, then we have a pointer somewhere so we can't align
                        if (fieldAlignment > 0)
                        {
                            // otherwise, align the field on the alignment requirement of the field
                            int delta = (currentFieldAbsoluteOffset % fieldAlignment);
                            if (delta != 0)
                            {
                                currentFieldAbsoluteOffset += fieldAlignment - delta;
                            }
                        }

                        // Get correct offset (for handling union)
                        csField.Offset = currentFieldAbsoluteOffset;

                        // Handle bit fields : calculate BitOffset and BitMask for this field
                        if (previousFieldOffsetIndex != cppField.Offset)
                        {
                            cumulatedBitOffset = 0;
                        }
                        if (cppField.IsBitField)
                        {
                            int lastCumulatedBitOffset = cumulatedBitOffset;
                            cumulatedBitOffset        += cppField.BitOffset;
                            csField.BitMask            = ((1 << cppField.BitOffset) - 1);
                            csField.BitOffset          = lastCumulatedBitOffset;
                        }

                        var nextFieldIndex = fieldIndex + 1;
                        if ((previousFieldOffsetIndex == cppField.Offset) ||
                            (nextFieldIndex < fieldCount && ((CppField)currentStruct.Items[nextFieldIndex]).Offset == cppField.Offset))
                        {
                            if (previousFieldOffsetIndex != cppField.Offset)
                            {
                                maxSizeOfField = 0;
                            }
                            maxSizeOfField          = csField.Size > maxSizeOfField ? csField.Size : maxSizeOfField;
                            isNonSequential         = true;
                            csStruct.ExplicitLayout = true;
                            previousFieldSize       = 0;
                        }
                        else
                        {
                            previousFieldSize = csField.Size;
                        }
                        previousFieldOffsetIndex = cppField.Offset;
                    });
 private Domain BuildUpgradedDomain(NamingRules namingRules) =>
 BuildDomain(DomainUpgradeMode.PerformSafely, namingRules, typeof(V2.MyChildEntity));
Ejemplo n.º 24
0
        /// <summary>
        /// Maps a C++ Enum to a C# enum.
        /// </summary>
        /// <param name="newEnum">the C# enum.</param>
        private void Process(CsEnum newEnum)
        {
            var cppEnum = (CppEnum)newEnum.CppElement;

            // Get tag from C++ enum
            var tag = cppEnum.GetTagOrDefault <MappingRule>();

            // Determine enum type. Default is int
            string typeName = cppEnum.GetTypeNameWithMapping();

            switch (typeName)
            {
            case "byte":
                newEnum.Type   = typeof(byte);
                newEnum.SizeOf = 1;
                break;

            case "short":
                newEnum.Type   = typeof(short);
                newEnum.SizeOf = 1;
                break;

            case "int":
                newEnum.Type   = typeof(int);
                newEnum.SizeOf = 4;
                break;

            default:
                Logger.Error("Invalid type [{0}] for enum [{1}]. Types supported are : int, byte, short", typeName, cppEnum);
                break;
            }

            // Find Root Name of this enum
            // All enum items should start with the same root name and the root name should be at least 4 chars
            string rootName        = cppEnum.Name;
            string rootNameFound   = null;
            bool   isRootNameFound = false;

            for (int i = rootName.Length; i >= 4 && !isRootNameFound; i--)
            {
                rootNameFound = rootName.Substring(0, i);

                isRootNameFound = true;
                foreach (var cppEnumItem in cppEnum.EnumItems)
                {
                    if (!cppEnumItem.Name.StartsWith(rootNameFound))
                    {
                        isRootNameFound = false;
                        break;
                    }
                }
            }
            if (isRootNameFound)
            {
                rootName = rootNameFound;
            }

            // Create enum items for enum
            foreach (var cppEnumItem in cppEnum.EnumItems)
            {
                string enumName  = NamingRules.Rename(cppEnumItem, rootName);
                string enumValue = cppEnumItem.Value;

                var csharpEnumItem = new CsEnumItem(enumName, enumValue)
                {
                    CppElement = cppEnumItem
                };

                newEnum.Add(csharpEnumItem);

                if (cppEnumItem.Name != "None")
                {
                    Manager.BindType(cppEnumItem.Name, csharpEnumItem);
                }
            }

            bool tryToAddNone = tag.EnumHasNone.HasValue ? tag.EnumHasNone.Value : false;

            // If C++ enum name is ending with FLAG OR FLAGS
            // Then tag this enum as flags and add None if necessary
            if (cppEnum.Name.EndsWith("FLAG") || cppEnum.Name.EndsWith("FLAGS"))
            {
                newEnum.IsFlag = true;

                if (!tag.EnumHasNone.HasValue)
                {
                    tryToAddNone = !newEnum.Items.Cast <CsEnumItem>().Any(item => item.Name == "None");
                }
            }

            // Add None value
            if (tryToAddNone)
            {
                var csharpEnumItem = new CsEnumItem("None", "0");
                csharpEnumItem.CppElement = new CppElement {
                    Description = "None."
                };
                newEnum.Add(csharpEnumItem);
            }
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Maps a C++ Enum to a C# enum.
        /// </summary>
        /// <param name="newEnum">the C# enum.</param>
        public override void Process(CsEnum newEnum)
        {
            var cppEnum = (CppEnum)newEnum.CppElement;

            // Determine enum type. Default is int
            var typeName = cppEnum.GetTypeNameWithMapping();

            switch (typeName)
            {
            case "byte":
                newEnum.UnderlyingType = typeRegistry.ImportType(typeof(byte));
                break;

            case "short":
                newEnum.UnderlyingType = typeRegistry.ImportType(typeof(short));
                break;

            case "ushort":
                newEnum.UnderlyingType = typeRegistry.ImportType(typeof(ushort));
                break;

            case "int":
                newEnum.UnderlyingType = typeRegistry.ImportType(typeof(int));
                break;

            case "uint":
                newEnum.UnderlyingType = typeRegistry.ImportType(typeof(uint));
                break;

            default:
                Logger.Error(LoggingCodes.InvalidUnderlyingType, "Invalid type [{0}] for enum [{1}]. Types supported are : int, byte, short", typeName, cppEnum);
                break;
            }

            // Find Root Name of this enum
            // All enum items should start with the same root name and the root name should be at least 4 chars
            string rootName        = cppEnum.Name;
            string rootNameFound   = null;
            bool   isRootNameFound = false;

            for (int i = rootName.Length; i >= 4 && !isRootNameFound; i--)
            {
                rootNameFound = rootName.Substring(0, i);

                isRootNameFound = true;
                foreach (var cppEnumItem in cppEnum.EnumItems)
                {
                    if (!cppEnumItem.Name.StartsWith(rootNameFound))
                    {
                        isRootNameFound = false;
                        break;
                    }
                }
            }
            if (isRootNameFound)
            {
                rootName = rootNameFound;
            }

            // Create enum items for enum
            foreach (var cppEnumItem in cppEnum.EnumItems)
            {
                string enumName  = NamingRules.Rename(cppEnumItem, rootName);
                string enumValue = cppEnumItem.Value;

                var csharpEnumItem = new CsEnumItem(enumName, enumValue)
                {
                    CppElement = cppEnumItem
                };

                newEnum.Add(csharpEnumItem);
            }

            var rule = cppEnum.GetMappingRule();

            bool tryToAddNone = rule.EnumHasNone ?? false;

            // If C++ enum name is ending with FLAG OR FLAGS
            // Then tag this enum as flags and add None if necessary
            if (cppEnum.Name.EndsWith("FLAG") || cppEnum.Name.EndsWith("FLAGS"))
            {
                newEnum.IsFlag = true;

                if (!rule.EnumHasNone.HasValue)
                {
                    tryToAddNone = !newEnum.EnumItems.Any(item => item.Name == "None");
                }
            }

            // Add None value
            if (tryToAddNone)
            {
                var csharpEnumItem = new CsEnumItem("None", "0")
                {
                    CppElementName = "None",
                    Description    = "None"
                };
                newEnum.Add(csharpEnumItem);
            }
        }
        private Domain BuildDomain(DomainUpgradeMode upgradeMode, NamingRules namingRules, Type sampleType)
        {
            var configuration = BuildDomainConfiguration(upgradeMode, namingRules, sampleType);

            return(Domain.Build(configuration));
        }