SharpGen/Model/CsMarshalBase.cs (103 lines of code) (raw):

// Copyright (c) 2010-2014 SharpDX - Alexandre Mutel // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System; using System.Collections.Generic; using System.Collections.Immutable; using SharpGen.CppModel; using SharpGen.Generator.Marshallers; using SharpGen.Logging; using SharpGen.Transform; namespace SharpGen.Model { public abstract class CsMarshalBase : CsBase { #nullable enable private IReadOnlyList<MarshallableRelation>? relations; private CsTypeBase? marshalType; private CsTypeBase publicType; /// <summary> /// Public type used for element. /// </summary> public CsTypeBase PublicType { get => publicType; set => publicType = value ?? throw new ArgumentException("Public type cannot be null"); } /// <summary> /// Internal type used for marshalling to native. /// </summary> public CsTypeBase MarshalType { get => marshalType ?? PublicType; set => marshalType = value; } public void SetPublicResetMarshalType(CsTypeBase type) { PublicType = type; marshalType = null; } public virtual bool HasPointer { get; } public ArraySpecification? ArraySpecification { get; private set; } public bool IsWideChar { get; set; } public virtual bool IsArray { get => ArraySpecification.HasValue; set { switch (value) { case true when ArraySpecification.HasValue: return; case true: ArraySpecification = new ArraySpecification(); return; case false: ArraySpecification = null; break; } } } public int ArrayDimensionValue => ArraySpecification is {Dimension: { } value} ? checked((int) value) : 0; public uint ArrayDimensionValueUnsigned => ArraySpecification is {Dimension: { } value} ? value : 0; public IReadOnlyList<MarshallableRelation> Relations { get => relations ?? ImmutableList<MarshallableRelation>.Empty; set => relations = value; } public bool IsBoolToInt => MarshalType is CsFundamentalType {IsIntegerType: true} && PublicType == TypeRegistry.Boolean; public uint Size => MarshalType.Size * (ArraySpecification is {Dimension: { } value} ? Math.Max(value, 1) : 1); public bool IsValueType => PublicType is CsStruct {GenerateAsClass: false} or CsEnum or CsFundamentalType {IsValueType: true}; public bool IsInterface => PublicType is CsInterface; public bool IsStructClass => PublicType is CsStruct {GenerateAsClass: true}; public bool IsPrimitive => PublicType is CsFundamentalType {IsPrimitive: true} or CsEnum; public bool IsString => PublicType is CsFundamentalType {IsString: true}; public bool HasNativeValueType => PublicType is CsStruct {HasMarshalType: true}; public bool IsStaticMarshal => PublicType is CsStruct {IsStaticMarshal: true}; public bool IsInterfaceArray => PublicType is CsInterfaceArray; /// <remarks> /// Used in 2 cases: /// <list type="number"> /// <item> /// <description>Backing field in structs for non-trivial cases</description> /// </item> /// <item> /// <description>Pinned Span element pointer from <see cref="ArrayMarshallerBase"/></description> /// </item> /// </list> /// </remarks> public string IntermediateMarshalName => Name[0] == '@' ? $"_{Name.Substring(1)}" : $"_{Name}"; public bool MappedToDifferentPublicType => MarshalType != PublicType && !IsBoolToInt && !(MarshalType is CsFundamentalType {IsPointer: true} && HasPointer) && !(IsInterface && HasPointer); #nullable restore protected CsMarshalBase(Ioc ioc, CppElement cppElement, string name) : base(cppElement, name) { if (cppElement is CppMarshallable cppMarshallable) { HasPointer = cppMarshallable.HasPointer; ArraySpecification = ParseArrayDimensionValue(cppMarshallable.IsArray, cppMarshallable.ArrayDimension); } ArraySpecification? ParseArrayDimensionValue(bool isArray, string arrayDimension) { if (!isArray || string.IsNullOrEmpty(arrayDimension)) return null; if (arrayDimension.Contains(",")) { ioc.Logger.Warning(null, "SharpGen might not handle multidimensional arrays properly."); } // TODO: handle multidimensional arrays return uint.TryParse(arrayDimension, out var arrayDimensionValue) && arrayDimensionValue >= 1 ? new ArraySpecification(arrayDimensionValue) : null; } } public override IEnumerable<CsBase> AdditionalItems => AppendNonNull( base.AdditionalItems, PublicType, MarshalType ); } }