protected override ExpressionSyntax GenerateAllocationExpression( TypePositionInfo info, StubCodeContext context, SyntaxToken byteLengthIdentifier, out bool allocationRequiresByteLength) { allocationRequiresByteLength = false; return(CastExpression( AsNativeType(info), StringMarshaller.AllocationExpression(CharEncoding.Utf16, context.GetIdentifiers(info).managed))); }
public override IEnumerable <StatementSyntax> Generate(TypePositionInfo info, StubCodeContext context) { (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); switch (context.CurrentStage) { case StubCodeContext.Stage.Setup: if (TryGenerateSetupSyntax(info, context, out StatementSyntax conditionalAllocSetup)) { yield return(conditionalAllocSetup); } break; case StubCodeContext.Stage.Marshal: if (info.RefKind != RefKind.Out) { // <native> = (byte*)Marshal.StringToCoTaskMemAnsi(<managed>); BlockSyntax windowsBlock = Block( ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(nativeIdentifier), CastExpression( AsNativeType(info), StringMarshaller.AllocationExpression(CharEncoding.Ansi, managedIdentifier))))); // Set the allocation marker to true if it is being used if (UsesConditionalStackAlloc(info, context)) { // <allocationMarker> = true windowsBlock = windowsBlock.AddStatements( ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(GetAllocationMarkerIdentifier(info, context)), LiteralExpression(SyntaxKind.TrueLiteralExpression)))); } // [Compat] The generated source for ANSI string marshalling does not optimize for // allocating on the stack based on the string length. It always uses AllocCoTaskMem. // if (OperatingSystem.IsWindows()) // { // <native> = (byte*)Marshal.StringToCoTaskMemAnsi(<managed>); // } // else // { // << marshal as UTF-8 >> // } yield return(IfStatement(IsWindows, windowsBlock, ElseClause( Block(_utf8StringMarshaller.Generate(info, context))))); } break; case StubCodeContext.Stage.Unmarshal: if (info.IsManagedReturnPosition || (info.IsByRef && info.RefKind != RefKind.In)) { // if (OperatingSystem.IsWindows()) // { // <managed> = <native> == null ? null : new string((sbyte*)<native>); // } // else // { // << unmarshal as UTF-8 >> // } yield return(IfStatement(IsWindows, Block( ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(managedIdentifier), ConditionalExpression( BinaryExpression( SyntaxKind.EqualsExpression, IdentifierName(nativeIdentifier), LiteralExpression(SyntaxKind.DefaultLiteralExpression)), LiteralExpression(SyntaxKind.NullLiteralExpression), ObjectCreationExpression( PredefinedType(Token(SyntaxKind.StringKeyword)), ArgumentList(SingletonSeparatedList( Argument( CastExpression( PointerType(PredefinedType(Token(SyntaxKind.SByteKeyword))), IdentifierName(nativeIdentifier))))), initializer: null))))), ElseClause( Block(_utf8StringMarshaller.Generate(info, context))))); } break; case StubCodeContext.Stage.Cleanup: yield return(GenerateConditionalAllocationFreeSyntax(info, context)); break; } }