Skip to content

Commit

Permalink
Improve string array handling
Browse files Browse the repository at this point in the history
  • Loading branch information
badcel committed Sep 16, 2023
1 parent 5fce9ea commit b2d13a3
Show file tree
Hide file tree
Showing 39 changed files with 873 additions and 204 deletions.
9 changes: 9 additions & 0 deletions src/Generation/Generator/Model/PlatformStringArray.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Generator.Model;

internal static class PlatformStringArray
{
public static string GetInternalOwnedHandleName() => "GLib.Internal.PlatformStringArrayNullTerminatedOwnedHandle";
public static string GetInternalUnownedHandleName() => "GLib.Internal.PlatformStringArrayNullTerminatedUnownedHandle";
public static string GetInternalContainerHandleName() => "GLib.Internal.PlatformStringArrayNullTerminatedContainerHandle";
public static string GetInternalHandleName() => "GLib.Internal.PlatformStringArrayNullTerminatedHandle";
}
9 changes: 9 additions & 0 deletions src/Generation/Generator/Model/Utf8StringArray.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Generator.Model;

internal static class Utf8StringArray
{
public static string GetInternalOwnedHandleName() => "GLib.Internal.Utf8StringArrayNullTerminatedOwnedHandle";
public static string GetInternalUnownedHandleName() => "GLib.Internal.Utf8StringArrayNullTerminatedUnownedHandle";
public static string GetInternalContainerHandleName() => "GLib.Internal.Utf8StringArrayNullTerminatedContainerHandle";
public static string GetInternalHandleName() => "GLib.Internal.Utf8StringArrayNullTerminatedHandle";
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ internal static class CallbackParameters
new Parameter.InterfaceArray(),
new Parameter.NativeUnsignedIntegerArray(),
new Parameter.OpaqueTypedRecordCallback(),
new Parameter.PlatformStringArrayCallback(),
new Parameter.Pointer(),
new Parameter.PointerAlias(),
new Parameter.PointerArray(),
Expand All @@ -34,9 +35,9 @@ internal static class CallbackParameters
new Parameter.RecordCallback(), //Callbacks do not support record safe handles in parameters
new Parameter.RecordGLibPtrArray(),
new Parameter.String(),
new Parameter.StringArray(),
new Parameter.Union(),
new Parameter.UnsignedPointer(),
new Parameter.Utf8StringArrayCallback(),
new Parameter.Void(),
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;

namespace Generator.Renderer.Internal.Parameter;

internal class PlatformStringArray : ParameterConverter
{
public bool Supports(GirModel.AnyType anyType)
{
return anyType.IsArray<GirModel.PlatformString>();
}

public RenderableParameter Convert(GirModel.Parameter parameter)
{
return new RenderableParameter(
Attribute: string.Empty,
Direction: GetAttribute(parameter),
NullableTypeName: GetNullableTypeName(parameter),
Name: Model.Parameter.GetName(parameter)
);
}

private static string GetNullableTypeName(GirModel.Parameter parameter)
{
return parameter switch
{
{ Transfer: GirModel.Transfer.None, AnyTypeOrVarArgs.AsT0.AsT1.Length: null } => Model.PlatformStringArray.GetInternalHandleName(),
{ Transfer: GirModel.Transfer.Full, AnyTypeOrVarArgs.AsT0.AsT1.Length: null } => Model.PlatformStringArray.GetInternalUnownedHandleName(),
{ Transfer: GirModel.Transfer.Container, AnyTypeOrVarArgs.AsT0.AsT1.Length: null } => throw new Exception("Transfer container not supported for utf8 string arrays"),
{ AnyTypeOrVarArgs.AsT0.AsT1.Length: not null} => Model.ArrayType.GetName(parameter.AnyTypeOrVarArgs.AsT0.AsT1),
_ => throw new Exception("Can't detect typename for utf8 string array")
};
}

private static string GetAttribute(GirModel.Parameter parameter)
{
return parameter.AnyTypeOrVarArgs.AsT0.AsT1.Length switch
{
null => string.Empty,
{ } l => MarshalAs.UnmanagedLpArray(sizeParamIndex: l)
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
namespace Generator.Renderer.Internal.Parameter;

internal class PlatformStringArrayCallback : ParameterConverter
{
public bool Supports(GirModel.AnyType anyType)
{
return anyType.IsArray<GirModel.PlatformString>();
}

public RenderableParameter Convert(GirModel.Parameter parameter)
{
return new RenderableParameter(
Attribute: GetAttribute(parameter),
Direction: string.Empty,
NullableTypeName: GetNullableTypeName(parameter),
Name: Model.Parameter.GetName(parameter)
);
}

private static string GetNullableTypeName(GirModel.Parameter parameter)
{
return parameter switch
{
// Arrays of string which do not transfer ownership and have no length index can not be marshalled automatically
{ Transfer: GirModel.Transfer.None, AnyTypeOrVarArgs.AsT0.AsT1.Length: null } => Model.Type.Pointer,
_ => Model.ArrayType.GetName(parameter.AnyTypeOrVarArgs.AsT0.AsT1)
};
}

private static string GetAttribute(GirModel.Parameter parameter)
{
return parameter.AnyTypeOrVarArgs.AsT0.AsT1.Length switch
{
null => string.Empty,
{ } l => MarshalAs.UnmanagedLpArray(sizeParamIndex: l)
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;

namespace Generator.Renderer.Internal.Parameter;

internal class Utf8StringArray : ParameterConverter
{
public bool Supports(GirModel.AnyType anyType)
{
return anyType.IsArray<GirModel.Utf8String>();
}

public RenderableParameter Convert(GirModel.Parameter parameter)
{
return new RenderableParameter(
Attribute: string.Empty,
Direction: GetAttribute(parameter),
NullableTypeName: GetNullableTypeName(parameter),
Name: Model.Parameter.GetName(parameter)
);
}

private static string GetNullableTypeName(GirModel.Parameter parameter)
{
return parameter switch
{
{ Transfer: GirModel.Transfer.None, AnyTypeOrVarArgs.AsT0.AsT1.Length: null } => Model.Utf8StringArray.GetInternalHandleName(),
{ Transfer: GirModel.Transfer.Full, AnyTypeOrVarArgs.AsT0.AsT1.Length: null } => Model.Utf8StringArray.GetInternalUnownedHandleName(),
{ Transfer: GirModel.Transfer.Container, AnyTypeOrVarArgs.AsT0.AsT1.Length: null } => throw new Exception("Transfer container not supported for utf8 string arrays"),
{ AnyTypeOrVarArgs.AsT0.AsT1.Length: not null} => Model.ArrayType.GetName(parameter.AnyTypeOrVarArgs.AsT0.AsT1),
_ => throw new Exception("Can't detect typename for utf8 string array")
};
}

private static string GetAttribute(GirModel.Parameter parameter)
{
return parameter.AnyTypeOrVarArgs.AsT0.AsT1.Length switch
{
null => string.Empty,
{ } l => MarshalAs.UnmanagedLpArray(sizeParamIndex: l)
};
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
namespace Generator.Renderer.Internal.Parameter;

internal class StringArray : ParameterConverter
internal class Utf8StringArrayCallback : ParameterConverter
{
public bool Supports(GirModel.AnyType anyType)
{
return anyType.IsArray<GirModel.String>();
return anyType.IsArray<GirModel.Utf8String>();
}

public RenderableParameter Convert(GirModel.Parameter parameter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ internal static class Parameters
new Parameter.NativeUnsignedIntegerArray(),
new Parameter.OpaqueTypedRecord(),
new Parameter.OpaqueTypedRecordArray(),
new Parameter.PlatformStringArray(),
new Parameter.Pointer(),
new Parameter.PointerAlias(),
new Parameter.PointerArray(),
Expand All @@ -37,10 +38,10 @@ internal static class Parameters
new Parameter.RecordArray(),
new Parameter.RecordGLibPtrArray(),
new Parameter.String(),
new Parameter.StringArray(),
new Parameter.StringGLibPtrArray(),
new Parameter.Union(),
new Parameter.UnsignedPointer(),
new Parameter.Utf8StringArray(),
new Parameter.Void(),
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;

namespace Generator.Renderer.Internal.ParameterToManagedExpressions;

internal class PlatformStringArray : ToManagedParameterConverter
{
public bool Supports(GirModel.AnyType type)
=> type.IsArray<GirModel.PlatformString>();

public void Initialize(ParameterToManagedData parameterData, IEnumerable<ParameterToManagedData> parameters)
{
var arrayType = parameterData.Parameter.AnyTypeOrVarArgs.AsT0.AsT1;
if (arrayType.Length is null)
NullTerminatedArray(parameterData);
else
SizeBasedArray(parameterData);
}

private static void NullTerminatedArray(ParameterToManagedData parameterData)
{
var signatureName = Model.Parameter.GetName(parameterData.Parameter);
var callName = Model.Parameter.GetConvertedName(parameterData.Parameter);

var handleExpression = parameterData.Parameter switch
{
{ Transfer: GirModel.Transfer.None } => $"new {Model.PlatformStringArray.GetInternalUnownedHandleName()}({signatureName}).ConvertToStringArray()",
{ Transfer: GirModel.Transfer.Full } => $"new {Model.PlatformStringArray.GetInternalOwnedHandleName()}({signatureName}).ConvertToStringArray()",
_ => throw new Exception("Unknown transfer type for platform string array to managed expression")
};

parameterData.SetSignatureName(signatureName);
parameterData.SetExpression($"var {callName} = {handleExpression};");
parameterData.SetCallName(callName);
}

private static void SizeBasedArray(ParameterToManagedData parameterData)
{
var variableName = Model.Parameter.GetName(parameterData.Parameter);

parameterData.SetSignatureName(variableName);
parameterData.SetCallName(variableName);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;

namespace Generator.Renderer.Internal.ParameterToManagedExpressions;

internal class Utf8StringArray : ToManagedParameterConverter
{
public bool Supports(GirModel.AnyType type)
=> type.IsArray<GirModel.Utf8String>();

public void Initialize(ParameterToManagedData parameterData, IEnumerable<ParameterToManagedData> parameters)
{
var arrayType = parameterData.Parameter.AnyTypeOrVarArgs.AsT0.AsT1;
if (arrayType.Length is null)
NullTerminatedArray(parameterData);
else
SizeBasedArray(parameterData);
}

private static void NullTerminatedArray(ParameterToManagedData parameterData)
{
var signatureName = Model.Parameter.GetName(parameterData.Parameter);
var callName = Model.Parameter.GetConvertedName(parameterData.Parameter);

var handleExpression = parameterData.Parameter switch
{
{ Transfer: GirModel.Transfer.None } => $"new {Model.Utf8StringArray.GetInternalUnownedHandleName()}({signatureName}).ConvertToStringArray()",
{ Transfer: GirModel.Transfer.Full } => $"new {Model.Utf8StringArray.GetInternalOwnedHandleName()}({signatureName}).ConvertToStringArray()",
_ => throw new Exception("Unknown transfer type for utf8 string array to managed expression")
};

parameterData.SetSignatureName(signatureName);
parameterData.SetExpression($"var {callName} = {handleExpression};");
parameterData.SetCallName(callName);
}

private static void SizeBasedArray(ParameterToManagedData parameterData)
{
var variableName = Model.Parameter.GetName(parameterData.Parameter);

parameterData.SetSignatureName(variableName);
parameterData.SetCallName(variableName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ internal static class ParameterToManagedExpression
new ParameterToManagedExpressions.Enumeration(),
new ParameterToManagedExpressions.Interface(),
new ParameterToManagedExpressions.OpaqueTypedRecord(),
new ParameterToManagedExpressions.PlatformStringArray(),
new ParameterToManagedExpressions.Pointer(),
new ParameterToManagedExpressions.PointerAlias(),
new ParameterToManagedExpressions.PrimitiveValueType(),
Expand All @@ -23,7 +24,7 @@ internal static class ParameterToManagedExpression
new ParameterToManagedExpressions.Record(),
new ParameterToManagedExpressions.RecordArray(),
new ParameterToManagedExpressions.String(),
new ParameterToManagedExpressions.StringArray(),
new ParameterToManagedExpressions.Utf8StringArray(),
};

public static IReadOnlyList<ParameterToManagedData> Initialize(IEnumerable<GirModel.Parameter> parameters)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;

namespace Generator.Renderer.Internal.ReturnType;

internal class PlatformStringArray : ReturnTypeConverter
{
public bool Supports(GirModel.ReturnType returnType)
{
return returnType.AnyType.IsArray<GirModel.PlatformString>();
}

public RenderableReturnType Convert(GirModel.ReturnType returnType)
{
var arrayType = returnType.AnyType.AsT1;

var nullableTypeName = arrayType.Length is null
? NullTerminatedArray(returnType)
: SizeBasedArray();

return new RenderableReturnType(nullableTypeName);
}

private static string NullTerminatedArray(GirModel.ReturnType returnType)
{
return returnType switch
{
{ Transfer: GirModel.Transfer.Full } => Model.PlatformStringArray.GetInternalOwnedHandleName(),
{ Transfer: GirModel.Transfer.None } => Model.PlatformStringArray.GetInternalUnownedHandleName(),
{ Transfer: GirModel.Transfer.Container } => Model.PlatformStringArray.GetInternalContainerHandleName(),
_ => throw new Exception("Unknown transfer type for platform string array return value")
};
}

private static string SizeBasedArray()
{
return "string[]";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Generator.Renderer.Internal.ReturnType;

internal class PlatformStringArrayInCallback : ReturnTypeConverter
{
public bool Supports(GirModel.ReturnType returnType)
{
return returnType.AnyType.IsArray<GirModel.PlatformString>();
}

public RenderableReturnType Convert(GirModel.ReturnType returnType)
{
var arrayType = returnType.AnyType.AsT1;
var isMarshalAble = returnType.Transfer != GirModel.Transfer.None || arrayType.Length != null;
var nullableTypeName = isMarshalAble
? Model.ArrayType.GetName(arrayType)
: Model.Type.Pointer;

return new RenderableReturnType(nullableTypeName);
}
}
Loading

0 comments on commit b2d13a3

Please sign in to comment.