SharpGen/Generator/Marshallers/BoolToIntArrayMarshaller.cs (102 lines of code) (raw):
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using SharpGen.Model;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
namespace SharpGen.Generator.Marshallers
{
internal sealed class BoolToIntArrayMarshaller : ArrayMarshallerBase
{
public override bool CanMarshal(CsMarshalBase csElement) => csElement.IsBoolToInt && csElement.IsArray;
public override StatementSyntax GenerateManagedToNative(CsMarshalBase csElement, bool singleStackFrame)
{
var marshalStorage = GetMarshalStorageLocation(csElement);
// TODO: Reverse-callback support?
StatementSyntax value;
if (singleStackFrame)
value = EmitConvertToIntArray(marshalStorage);
else
{
marshalStorage = PrefixUnaryExpression(SyntaxKind.AddressOfExpression, marshalStorage);
value = FixedStatement(
VariableDeclaration(
GetMarshalTypeSyntax(csElement),
SingletonSeparatedList(
VariableDeclarator(PtrIdentifier, default, EqualsValueClause(marshalStorage))
)
),
EmitConvertToIntArray(PtrIdentifierName)
);
}
return GenerateNullCheckIfNeeded(csElement, value);
ExpressionStatementSyntax EmitConvertToIntArray(ExpressionSyntax destination) => ExpressionStatement(
InvocationExpression(
MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
GlobalNamespace.GetTypeNameSyntax(WellKnownName.BooleanHelpers),
IdentifierName("ConvertToIntArray")
),
ArgumentList(
SeparatedList(
new[]
{
Argument(IdentifierName(csElement.Name)),
Argument(destination)
}
)
)
)
);
}
public override StatementSyntax GenerateNativeCleanup(CsMarshalBase csElement, bool singleStackFrame) => null;
public override StatementSyntax GenerateNativeToManaged(CsMarshalBase csElement, bool singleStackFrame)
{
var marshalStorage = GetMarshalStorageLocation(csElement);
StatementSyntax value;
if (singleStackFrame)
{
value = EmitConvertToBoolArray(marshalStorage);
}
else if (csElement is CsField)
{
marshalStorage = PrefixUnaryExpression(SyntaxKind.AddressOfExpression, marshalStorage);
value = FixedStatement(
VariableDeclaration(
GetMarshalTypeSyntax(csElement),
SingletonSeparatedList(
VariableDeclarator(PtrIdentifier, default, EqualsValueClause(marshalStorage))
)
),
EmitConvertToBoolArray(PtrIdentifierName)
);
}
else // Reverse-callbacks
{
value = EmitConvertToBoolArray(marshalStorage);
}
return GenerateNullCheckIfNeeded(csElement, value);
ExpressionStatementSyntax EmitConvertToBoolArray(ExpressionSyntax storage) => ExpressionStatement(
InvocationExpression(
MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
GlobalNamespace.GetTypeNameSyntax(WellKnownName.BooleanHelpers),
IdentifierName("ConvertToBoolArray")
),
ArgumentList(
SeparatedList(
new[]
{
Argument(storage),
Argument(IdentifierName(csElement.Name))
}
)
)
)
);
}
protected override TypeSyntax GetMarshalElementTypeSyntax(CsMarshalBase csElement) =>
ParseTypeName(csElement.MarshalType.QualifiedName);
public BoolToIntArrayMarshaller(Ioc ioc) : base(ioc)
{
}
}
}