SharpGen/Generator/Marshallers/MarshallerBase.CopyMemory.cs (89 lines of code) (raw):
using System;
using System.Linq;
using System.Runtime.CompilerServices;
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 abstract partial class MarshallerBase
{
protected static readonly PredefinedTypeSyntax TypeInt32 = PredefinedType(Token(SyntaxKind.IntKeyword));
protected static readonly PredefinedTypeSyntax TypeUInt32 = PredefinedType(Token(SyntaxKind.UIntKeyword));
protected const string FromIdentifier = "__from";
protected const string ToIdentifier = "__to";
protected ExpressionStatementSyntax GenerateCopyMemoryInvocation(ExpressionSyntax numBytesExpression,
bool castTo = true, bool castFrom = true) =>
GenerateCopyMemoryInvocation(
IntPtrArgumentWithOptionalCast(IdentifierName(ToIdentifier), castTo),
IntPtrArgumentWithOptionalCast(IdentifierName(FromIdentifier), castFrom),
numBytesExpression
);
protected static ExpressionSyntax IntPtrArgumentWithOptionalCast(ExpressionSyntax name, bool cast) =>
cast ? GeneratorHelpers.CastExpression(IntPtrType, name) : name;
protected ExpressionStatementSyntax GenerateCopyMemoryInvocation(
ExpressionSyntax destination, ExpressionSyntax source, ExpressionSyntax numBytesExpression
) => ExpressionStatement(
InvocationExpression(
MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
GlobalNamespace.GetTypeNameSyntax(WellKnownName.MemoryHelpers),
IdentifierName("CopyMemory")
),
ArgumentList(
SeparatedList(
new[]
{
Argument(destination),
Argument(source),
Argument(numBytesExpression)
}
)
)
)
);
protected ExpressionSyntax SizeOf(TypeSyntax elementType)
{
if (elementType is PredefinedTypeSyntax {Keyword: var predefinedType})
{
static LiteralExpressionSyntax LiteralSizeOf(uint size) => LiteralExpression(
SyntaxKind.NumericLiteralExpression, Literal(size)
);
bool CheckKinds(params SyntaxKind[] kinds) => kinds.Any(x => predefinedType.IsKind(x));
if (CheckKinds(SyntaxKind.ByteKeyword, SyntaxKind.SByteKeyword))
return LiteralSizeOf(1);
if (CheckKinds(SyntaxKind.ShortKeyword, SyntaxKind.UShortKeyword))
return LiteralSizeOf(2);
if (CheckKinds(SyntaxKind.IntKeyword, SyntaxKind.UIntKeyword))
return LiteralSizeOf(4);
if (CheckKinds(SyntaxKind.LongKeyword, SyntaxKind.ULongKeyword))
return LiteralSizeOf(8);
}
ExpressionSyntax value = elementType switch
{
QualifiedNameSyntax qualifiedName when qualifiedName.IsEquivalentTo(GeneratorHelpers.IntPtrType) =>
MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression, qualifiedName, IdentifierName(nameof(IntPtr.Size))
),
QualifiedNameSyntax qualifiedName when qualifiedName.IsEquivalentTo(GeneratorHelpers.UIntPtrType) =>
MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression, qualifiedName, IdentifierName(nameof(UIntPtr.Size))
),
_ => InvocationExpression(
MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
GlobalNamespace.GetTypeNameSyntax(BuiltinType.Unsafe),
GenericName(
Identifier(nameof(Unsafe.SizeOf)),
TypeArgumentList(SingletonSeparatedList(elementType))
)
)
)
};
return GeneratorHelpers.CastExpression(TypeUInt32, value);
}
protected ExpressionSyntax SizeOf(CsTypeBase elementType) => SizeOf(ParseTypeName(elementType.QualifiedName));
}
}