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 Oct 11, 2023
1 parent c901059 commit 27abfa5
Show file tree
Hide file tree
Showing 44 changed files with 2,048 additions and 205 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,88 @@
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 parameter.AnyTypeOrVarArgs.AsT0.AsT1.Length is null
? ParameterWithoutLength(parameter)
: ParameterWithLength(parameter);
}

private static RenderableParameter ParameterWithLength(GirModel.Parameter parameter)
{
var length = parameter.AnyTypeOrVarArgs.AsT0.AsT1.Length ?? throw new Exception("Length must not be null");

return new RenderableParameter(
Attribute: MarshalAs.UnmanagedLpArray(sizeParamIndex: length),
Direction: string.Empty,
NullableTypeName: Model.ArrayType.GetName(parameter.AnyTypeOrVarArgs.AsT0.AsT1),
Name: Model.Parameter.GetName(parameter)
);
}

private static RenderableParameter ParameterWithoutLength(GirModel.Parameter parameter)
{
return parameter.Direction switch
{
GirModel.Direction.In => ParameterWithoutLengthIn(parameter),
GirModel.Direction.Out => ParameterWithoutLengthOut(parameter),
_ => throw new Exception("Unknown direction for parameter")
};
}

private static RenderableParameter ParameterWithoutLengthIn(GirModel.Parameter parameter)
{
if (parameter.AnyTypeOrVarArgs.AsT0.AsT1.Length is not null)
throw new Exception("Length must be null");

if (parameter.Direction != GirModel.Direction.In)
throw new Exception("Direction must be in");

var nullableTypeName = parameter switch
{
{ Transfer: GirModel.Transfer.None } => Model.PlatformStringArray.GetInternalHandleName(),
{ Transfer: GirModel.Transfer.Full } => Model.PlatformStringArray.GetInternalUnownedHandleName(),
{ Transfer: GirModel.Transfer.Container } => throw new Exception("Transfer container not supported for platform string arrays"),
_ => throw new Exception("Can't detect typename for platform string array")
};

return new RenderableParameter(
Attribute: string.Empty,
Direction: ParameterDirection.In(),
NullableTypeName: nullableTypeName,
Name: Model.Parameter.GetName(parameter)
);
}

private static RenderableParameter ParameterWithoutLengthOut(GirModel.Parameter parameter)
{
if (parameter.AnyTypeOrVarArgs.AsT0.AsT1.Length is not null)
throw new Exception("Length must be null");

if (parameter.Direction != GirModel.Direction.Out)
throw new Exception("Direction must be out");

var nullableTypeName = parameter switch
{
{ Transfer: GirModel.Transfer.None } => Model.PlatformStringArray.GetInternalUnownedHandleName(),
{ Transfer: GirModel.Transfer.Full } => Model.PlatformStringArray.GetInternalOwnedHandleName(),
{ Transfer: GirModel.Transfer.Container } => Model.PlatformStringArray.GetInternalContainerHandleName(),
_ => throw new Exception("Can't detect typename for platform string array")
};

return new RenderableParameter(
Attribute: string.Empty,
Direction: ParameterDirection.Out(),
NullableTypeName: nullableTypeName,
Name: Model.Parameter.GetName(parameter)
);
}
}
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,88 @@
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 parameter.AnyTypeOrVarArgs.AsT0.AsT1.Length is null
? ParameterWithoutLength(parameter)
: ParameterWithLength(parameter);
}

private static RenderableParameter ParameterWithLength(GirModel.Parameter parameter)
{
var length = parameter.AnyTypeOrVarArgs.AsT0.AsT1.Length ?? throw new Exception("Length must not be null");

return new RenderableParameter(
Attribute: MarshalAs.UnmanagedLpArray(sizeParamIndex: length),
Direction: string.Empty,
NullableTypeName: Model.ArrayType.GetName(parameter.AnyTypeOrVarArgs.AsT0.AsT1),
Name: Model.Parameter.GetName(parameter)
);
}

private static RenderableParameter ParameterWithoutLength(GirModel.Parameter parameter)
{
return parameter.Direction switch
{
GirModel.Direction.In => ParameterWithoutLengthIn(parameter),
GirModel.Direction.Out => ParameterWithoutLengthOut(parameter),
_ => throw new Exception("Unknown direction for parameter")
};
}

private static RenderableParameter ParameterWithoutLengthIn(GirModel.Parameter parameter)
{
if (parameter.AnyTypeOrVarArgs.AsT0.AsT1.Length is not null)
throw new Exception("Length must be null");

if (parameter.Direction != GirModel.Direction.In)
throw new Exception("Direction must be in");

var nullableTypeName = parameter switch
{
{ Transfer: GirModel.Transfer.None } => Model.Utf8StringArray.GetInternalHandleName(),
{ Transfer: GirModel.Transfer.Full } => Model.Utf8StringArray.GetInternalUnownedHandleName(),
{ Transfer: GirModel.Transfer.Container } => throw new Exception("Transfer container not supported for utf8 string arrays"),
_ => throw new Exception("Can't detect typename for utf8 string array")
};

return new RenderableParameter(
Attribute: string.Empty,
Direction: ParameterDirection.In(),
NullableTypeName: nullableTypeName,
Name: Model.Parameter.GetName(parameter)
);
}

private static RenderableParameter ParameterWithoutLengthOut(GirModel.Parameter parameter)
{
if (parameter.AnyTypeOrVarArgs.AsT0.AsT1.Length is not null)
throw new Exception("Length must be null");

if (parameter.Direction != GirModel.Direction.Out)
throw new Exception("Direction must be out");

var nullableTypeName = parameter switch
{
{ Transfer: GirModel.Transfer.None } => Model.Utf8StringArray.GetInternalUnownedHandleName(),
{ Transfer: GirModel.Transfer.Full } => Model.Utf8StringArray.GetInternalOwnedHandleName(),
{ Transfer: GirModel.Transfer.Container } => Model.Utf8StringArray.GetInternalContainerHandleName(),
_ => throw new Exception("Can't detect typename for utf8 string array")
};

return new RenderableParameter(
Attribute: string.Empty,
Direction: ParameterDirection.Out(),
NullableTypeName: nullableTypeName,
Name: Model.Parameter.GetName(parameter)
);
}
}
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.

Loading

0 comments on commit 27abfa5

Please sign in to comment.