From 27abfa5cf817d1059cb203daccf33e1529afd8ad Mon Sep 17 00:00:00 2001 From: badcel <1218031+badcel@users.noreply.github.com> Date: Tue, 12 Sep 2023 15:02:13 +0200 Subject: [PATCH] Improve string array handling --- .../Generator/Model/PlatformStringArray.cs | 9 + .../Generator/Model/Utf8StringArray.cs | 9 + .../Internal/Parameter/CallbackParameters.cs | 3 +- .../Converter/PlatformStringArray.cs | 88 ++++++ .../Converter/PlatformStringArrayCallback.cs | 38 +++ .../Parameter/Converter/Utf8StringArray.cs | 88 ++++++ ...ingArray.cs => Utf8StringArrayCallback.cs} | 4 +- .../Renderer/Internal/Parameter/Parameters.cs | 3 +- .../Converter/PlatformStringArray.cs | 44 +++ .../Converter/StringArray.cs | 30 -- .../Converter/Utf8StringArray.cs | 44 +++ .../ParameterToManagedExpression.cs | 3 +- .../Converter/PlatformStringArray.cs | 38 +++ .../PlatformStringArrayInCallback.cs | 20 ++ .../ReturnType/Converter/Utf8StringArray.cs | 38 +++ ...gArray.cs => Utf8StringArrayInCallback.cs} | 4 +- .../Internal/ReturnType/ReturnTypeRenderer.cs | 3 +- .../ReturnType/ReturnTypeRendererCallback.cs | 3 +- .../Public/Parameter/Converter/StringArray.cs | 2 +- .../Converter/PlatformStringArray.cs | 93 ++++++ .../Converter/StringArray.cs | 35 --- .../Converter/Utf8StringArray.cs | 93 ++++++ .../ParameterToNativeExpression.cs | 3 +- .../ReturnType/Converter/StringArray.cs | 2 +- .../Converter/PlatformStringArray.cs | 27 ++ .../Converter/StringArray.cs | 16 - .../Converter/Utf8StringArray.cs | 27 ++ .../ReturnTypeToManagedExpression.cs | 3 +- ...PlatformStringArrayNullTerminatedHandle.cs | 182 +++++++++++ src/Libs/GLib-2.0/Internal/StringHelper.cs | 94 +----- .../Utf8StringArrayNullTerminatedHandle.cs | 144 +++++++++ .../GLib-2.0/Internal/Utf8StringHandle.cs | 4 +- src/Libs/GObject-2.0/Public/Value.cs | 7 +- src/Libs/WebKit-6.0/Public/UserScript.cs | 12 - ...form-string-array-null-terminated-tester.c | 294 ++++++++++++++++++ ...form-string-array-null-terminated-tester.h | 29 ++ ...utf8-string-array-null-terminated-tester.c | 294 ++++++++++++++++++ ...utf8-string-array-null-terminated-tester.h | 29 ++ src/Native/GirTestLib/girtest.h | 2 + src/Native/GirTestLib/meson.build | 4 + .../WebKit-6.0/JavascriptCall/Program.cs | 4 +- .../WebKit-6.0/JavascriptCallback/Program.cs | 4 +- .../PlatformStringArrayNullTerminatedTest.cs | 190 +++++++++++ .../Utf8StringArrayNullTerminatedTest.cs | 190 +++++++++++ 44 files changed, 2048 insertions(+), 205 deletions(-) create mode 100644 src/Generation/Generator/Model/PlatformStringArray.cs create mode 100644 src/Generation/Generator/Model/Utf8StringArray.cs create mode 100644 src/Generation/Generator/Renderer/Internal/Parameter/Converter/PlatformStringArray.cs create mode 100644 src/Generation/Generator/Renderer/Internal/Parameter/Converter/PlatformStringArrayCallback.cs create mode 100644 src/Generation/Generator/Renderer/Internal/Parameter/Converter/Utf8StringArray.cs rename src/Generation/Generator/Renderer/Internal/Parameter/Converter/{StringArray.cs => Utf8StringArrayCallback.cs} (91%) create mode 100644 src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/Converter/PlatformStringArray.cs delete mode 100644 src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/Converter/StringArray.cs create mode 100644 src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/Converter/Utf8StringArray.cs create mode 100644 src/Generation/Generator/Renderer/Internal/ReturnType/Converter/PlatformStringArray.cs create mode 100644 src/Generation/Generator/Renderer/Internal/ReturnType/Converter/PlatformStringArrayInCallback.cs create mode 100644 src/Generation/Generator/Renderer/Internal/ReturnType/Converter/Utf8StringArray.cs rename src/Generation/Generator/Renderer/Internal/ReturnType/Converter/{StringArray.cs => Utf8StringArrayInCallback.cs} (81%) create mode 100644 src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/Converter/PlatformStringArray.cs delete mode 100644 src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/Converter/StringArray.cs create mode 100644 src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/Converter/Utf8StringArray.cs create mode 100644 src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PlatformStringArray.cs delete mode 100644 src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/StringArray.cs create mode 100644 src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Utf8StringArray.cs create mode 100644 src/Libs/GLib-2.0/Internal/PlatformStringArrayNullTerminatedHandle.cs create mode 100644 src/Libs/GLib-2.0/Internal/Utf8StringArrayNullTerminatedHandle.cs delete mode 100644 src/Libs/WebKit-6.0/Public/UserScript.cs create mode 100644 src/Native/GirTestLib/girtest-platform-string-array-null-terminated-tester.c create mode 100644 src/Native/GirTestLib/girtest-platform-string-array-null-terminated-tester.h create mode 100644 src/Native/GirTestLib/girtest-utf8-string-array-null-terminated-tester.c create mode 100644 src/Native/GirTestLib/girtest-utf8-string-array-null-terminated-tester.h create mode 100644 src/Tests/Libs/GirTest-0.1.Tests/PlatformStringArrayNullTerminatedTest.cs create mode 100644 src/Tests/Libs/GirTest-0.1.Tests/Utf8StringArrayNullTerminatedTest.cs diff --git a/src/Generation/Generator/Model/PlatformStringArray.cs b/src/Generation/Generator/Model/PlatformStringArray.cs new file mode 100644 index 000000000..7baf3ba3f --- /dev/null +++ b/src/Generation/Generator/Model/PlatformStringArray.cs @@ -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"; +} diff --git a/src/Generation/Generator/Model/Utf8StringArray.cs b/src/Generation/Generator/Model/Utf8StringArray.cs new file mode 100644 index 000000000..b792d41dd --- /dev/null +++ b/src/Generation/Generator/Model/Utf8StringArray.cs @@ -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"; +} diff --git a/src/Generation/Generator/Renderer/Internal/Parameter/CallbackParameters.cs b/src/Generation/Generator/Renderer/Internal/Parameter/CallbackParameters.cs index 63b3c450d..f2565a7d1 100644 --- a/src/Generation/Generator/Renderer/Internal/Parameter/CallbackParameters.cs +++ b/src/Generation/Generator/Renderer/Internal/Parameter/CallbackParameters.cs @@ -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(), @@ -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(), }; diff --git a/src/Generation/Generator/Renderer/Internal/Parameter/Converter/PlatformStringArray.cs b/src/Generation/Generator/Renderer/Internal/Parameter/Converter/PlatformStringArray.cs new file mode 100644 index 000000000..0baa4ed14 --- /dev/null +++ b/src/Generation/Generator/Renderer/Internal/Parameter/Converter/PlatformStringArray.cs @@ -0,0 +1,88 @@ +using System; + +namespace Generator.Renderer.Internal.Parameter; + +internal class PlatformStringArray : ParameterConverter +{ + public bool Supports(GirModel.AnyType anyType) + { + return anyType.IsArray(); + } + + 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) + ); + } +} diff --git a/src/Generation/Generator/Renderer/Internal/Parameter/Converter/PlatformStringArrayCallback.cs b/src/Generation/Generator/Renderer/Internal/Parameter/Converter/PlatformStringArrayCallback.cs new file mode 100644 index 000000000..6e81a1ae8 --- /dev/null +++ b/src/Generation/Generator/Renderer/Internal/Parameter/Converter/PlatformStringArrayCallback.cs @@ -0,0 +1,38 @@ +namespace Generator.Renderer.Internal.Parameter; + +internal class PlatformStringArrayCallback : ParameterConverter +{ + public bool Supports(GirModel.AnyType anyType) + { + return anyType.IsArray(); + } + + 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) + }; + } +} diff --git a/src/Generation/Generator/Renderer/Internal/Parameter/Converter/Utf8StringArray.cs b/src/Generation/Generator/Renderer/Internal/Parameter/Converter/Utf8StringArray.cs new file mode 100644 index 000000000..606e6f863 --- /dev/null +++ b/src/Generation/Generator/Renderer/Internal/Parameter/Converter/Utf8StringArray.cs @@ -0,0 +1,88 @@ +using System; + +namespace Generator.Renderer.Internal.Parameter; + +internal class Utf8StringArray : ParameterConverter +{ + public bool Supports(GirModel.AnyType anyType) + { + return anyType.IsArray(); + } + + 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) + ); + } +} diff --git a/src/Generation/Generator/Renderer/Internal/Parameter/Converter/StringArray.cs b/src/Generation/Generator/Renderer/Internal/Parameter/Converter/Utf8StringArrayCallback.cs similarity index 91% rename from src/Generation/Generator/Renderer/Internal/Parameter/Converter/StringArray.cs rename to src/Generation/Generator/Renderer/Internal/Parameter/Converter/Utf8StringArrayCallback.cs index 41048a512..1a0dbe7cc 100644 --- a/src/Generation/Generator/Renderer/Internal/Parameter/Converter/StringArray.cs +++ b/src/Generation/Generator/Renderer/Internal/Parameter/Converter/Utf8StringArrayCallback.cs @@ -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(); + return anyType.IsArray(); } public RenderableParameter Convert(GirModel.Parameter parameter) diff --git a/src/Generation/Generator/Renderer/Internal/Parameter/Parameters.cs b/src/Generation/Generator/Renderer/Internal/Parameter/Parameters.cs index 14cef4f7e..4dd718bc4 100644 --- a/src/Generation/Generator/Renderer/Internal/Parameter/Parameters.cs +++ b/src/Generation/Generator/Renderer/Internal/Parameter/Parameters.cs @@ -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(), @@ -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(), }; diff --git a/src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/Converter/PlatformStringArray.cs b/src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/Converter/PlatformStringArray.cs new file mode 100644 index 000000000..ec3ca885e --- /dev/null +++ b/src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/Converter/PlatformStringArray.cs @@ -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(); + + public void Initialize(ParameterToManagedData parameterData, IEnumerable 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); + } +} diff --git a/src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/Converter/StringArray.cs b/src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/Converter/StringArray.cs deleted file mode 100644 index e8b66a6f3..000000000 --- a/src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/Converter/StringArray.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Collections.Generic; - -namespace Generator.Renderer.Internal.ParameterToManagedExpressions; - -internal class StringArray : ToManagedParameterConverter -{ - public bool Supports(GirModel.AnyType type) - => type.IsArray(); - - public void Initialize(ParameterToManagedData parameterData, IEnumerable parameters) - { - var arrayType = parameterData.Parameter.AnyTypeOrVarArgs.AsT0.AsT1; - if (parameterData.Parameter.Transfer == GirModel.Transfer.None && arrayType.Length == null) - { - var signatureName = Model.Parameter.GetName(parameterData.Parameter); - var callName = Model.Parameter.GetConvertedName(parameterData.Parameter); - - parameterData.SetSignatureName(signatureName); - parameterData.SetExpression($"var {callName} = GLib.Internal.StringHelper.ToStringArrayUtf8({signatureName});"); - parameterData.SetCallName(callName); - } - else - { - var variableName = Model.Parameter.GetName(parameterData.Parameter); - - parameterData.SetSignatureName(variableName); - parameterData.SetCallName(variableName); - } - } -} diff --git a/src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/Converter/Utf8StringArray.cs b/src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/Converter/Utf8StringArray.cs new file mode 100644 index 000000000..308aa5c1a --- /dev/null +++ b/src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/Converter/Utf8StringArray.cs @@ -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(); + + public void Initialize(ParameterToManagedData parameterData, IEnumerable 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); + } +} diff --git a/src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/ParameterToManagedExpression.cs b/src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/ParameterToManagedExpression.cs index 77958c7ae..f2ceba12b 100644 --- a/src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/ParameterToManagedExpression.cs +++ b/src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/ParameterToManagedExpression.cs @@ -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(), @@ -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 Initialize(IEnumerable parameters) diff --git a/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/PlatformStringArray.cs b/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/PlatformStringArray.cs new file mode 100644 index 000000000..4d2aaa0c2 --- /dev/null +++ b/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/PlatformStringArray.cs @@ -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(); + } + + 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[]"; + } +} diff --git a/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/PlatformStringArrayInCallback.cs b/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/PlatformStringArrayInCallback.cs new file mode 100644 index 000000000..f093f62b4 --- /dev/null +++ b/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/PlatformStringArrayInCallback.cs @@ -0,0 +1,20 @@ +namespace Generator.Renderer.Internal.ReturnType; + +internal class PlatformStringArrayInCallback : ReturnTypeConverter +{ + public bool Supports(GirModel.ReturnType returnType) + { + return returnType.AnyType.IsArray(); + } + + 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); + } +} diff --git a/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/Utf8StringArray.cs b/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/Utf8StringArray.cs new file mode 100644 index 000000000..9f1421fd8 --- /dev/null +++ b/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/Utf8StringArray.cs @@ -0,0 +1,38 @@ +using System; + +namespace Generator.Renderer.Internal.ReturnType; + +internal class Utf8StringArray : ReturnTypeConverter +{ + public bool Supports(GirModel.ReturnType returnType) + { + return returnType.AnyType.IsArray(); + } + + 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.Utf8StringArray.GetInternalOwnedHandleName(), + { Transfer: GirModel.Transfer.None } => Model.Utf8StringArray.GetInternalUnownedHandleName(), + { Transfer: GirModel.Transfer.Container } => Model.Utf8StringArray.GetInternalContainerHandleName(), + _ => throw new Exception("Unknown transfer type for utf8 string array return value") + }; + } + + private static string SizeBasedArray() + { + return "string[]"; + } +} diff --git a/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/StringArray.cs b/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/Utf8StringArrayInCallback.cs similarity index 81% rename from src/Generation/Generator/Renderer/Internal/ReturnType/Converter/StringArray.cs rename to src/Generation/Generator/Renderer/Internal/ReturnType/Converter/Utf8StringArrayInCallback.cs index 4b767d59a..f65bd74bd 100644 --- a/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/StringArray.cs +++ b/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/Utf8StringArrayInCallback.cs @@ -1,10 +1,10 @@ namespace Generator.Renderer.Internal.ReturnType; -internal class StringArray : ReturnTypeConverter +internal class Utf8StringArrayInCallback : ReturnTypeConverter { public bool Supports(GirModel.ReturnType returnType) { - return returnType.AnyType.IsArray(); + return returnType.AnyType.IsArray(); } public RenderableReturnType Convert(GirModel.ReturnType returnType) diff --git a/src/Generation/Generator/Renderer/Internal/ReturnType/ReturnTypeRenderer.cs b/src/Generation/Generator/Renderer/Internal/ReturnType/ReturnTypeRenderer.cs index 42644a44a..cb59dac28 100644 --- a/src/Generation/Generator/Renderer/Internal/ReturnType/ReturnTypeRenderer.cs +++ b/src/Generation/Generator/Renderer/Internal/ReturnType/ReturnTypeRenderer.cs @@ -14,6 +14,7 @@ internal static class ReturnTypeRenderer new ReturnType.InterfaceGLibPtrArray(), new ReturnType.OpaqueTypedRecord(), new ReturnType.PlatformString(), + new ReturnType.PlatformStringArray(), new ReturnType.Pointer(), new ReturnType.PointerAlias(), new ReturnType.PrimitiveValueType(), @@ -21,9 +22,9 @@ internal static class ReturnTypeRenderer new ReturnType.PrimitiveValueTypeArray(), new ReturnType.Record(), new ReturnType.RecordArray(), - new ReturnType.StringArray(), new ReturnType.Union(), new ReturnType.Utf8String(), + new ReturnType.Utf8StringArray(), new ReturnType.Void(), }; diff --git a/src/Generation/Generator/Renderer/Internal/ReturnType/ReturnTypeRendererCallback.cs b/src/Generation/Generator/Renderer/Internal/ReturnType/ReturnTypeRendererCallback.cs index dd6e2083a..4ce0d4c38 100644 --- a/src/Generation/Generator/Renderer/Internal/ReturnType/ReturnTypeRendererCallback.cs +++ b/src/Generation/Generator/Renderer/Internal/ReturnType/ReturnTypeRendererCallback.cs @@ -14,15 +14,16 @@ internal static class ReturnTypeRendererCallback new ReturnType.InterfaceGLibPtrArray(), new ReturnType.OpaqueTypedRecordCallback(), new ReturnType.PlatformStringInCallback(), + new ReturnType.PlatformStringArrayInCallback(), new ReturnType.Pointer(), new ReturnType.PrimitiveValueType(), new ReturnType.PrimitiveValueTypeAlias(), new ReturnType.PrimitiveValueTypeArray(), new ReturnType.RecordArray(), new ReturnType.RecordInCallback(), - new ReturnType.StringArray(), new ReturnType.Union(), new ReturnType.Utf8StringInCallback(), + new ReturnType.Utf8StringArrayInCallback(), new ReturnType.Void(), }; diff --git a/src/Generation/Generator/Renderer/Public/Parameter/Converter/StringArray.cs b/src/Generation/Generator/Renderer/Public/Parameter/Converter/StringArray.cs index 44247a172..8bab7e01b 100644 --- a/src/Generation/Generator/Renderer/Public/Parameter/Converter/StringArray.cs +++ b/src/Generation/Generator/Renderer/Public/Parameter/Converter/StringArray.cs @@ -17,7 +17,7 @@ public ParameterTypeData Create(GirModel.Parameter parameter) private static string GetNullableTypeName(GirModel.Parameter parameter) { - return Model.ArrayType.GetName(parameter.AnyTypeOrVarArgs.AsT0.AsT1); + return Model.ArrayType.GetName(parameter.AnyTypeOrVarArgs.AsT0.AsT1) + Nullable.Render(parameter); } private static string GetDirection(GirModel.Parameter parameter) => parameter switch diff --git a/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/Converter/PlatformStringArray.cs b/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/Converter/PlatformStringArray.cs new file mode 100644 index 000000000..1a3bb93d3 --- /dev/null +++ b/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/Converter/PlatformStringArray.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; + +namespace Generator.Renderer.Public.ParameterToNativeExpressions; + +internal class PlatformStringArray : ToNativeParameterConverter +{ + public bool Supports(GirModel.AnyType type) + => type.IsArray(); + + public void Initialize(ParameterToNativeData parameter, IEnumerable _) + { + var arrayType = parameter.Parameter.AnyTypeOrVarArgs.AsT0.AsT1; + if (arrayType.Length == null) + NullTerminatedArray(parameter); + else + SizeBasedArray(parameter); + } + + private static void NullTerminatedArray(ParameterToNativeData parameter) + { + switch (parameter.Parameter.Direction) + { + case GirModel.Direction.In: + NullTerminatedArrayIn(parameter); + break; + case GirModel.Direction.Out: + NullTerminatedArrayOut(parameter); + break; + default: + throw new Exception($"Unsupported direction {parameter.Parameter.Direction} for platform string array."); + } + } + + private static void NullTerminatedArrayIn(ParameterToNativeData parameter) + { + var signatureName = Model.Parameter.GetName(parameter.Parameter); + var nativeVariableName = signatureName + "Native"; + + var createExpression = parameter.Parameter switch + { + { Transfer: GirModel.Transfer.Full } => $"{Model.PlatformStringArray.GetInternalUnownedHandleName()}.Create({signatureName})", + { Transfer: GirModel.Transfer.None } => $"{Model.PlatformStringArray.GetInternalOwnedHandleName()}.Create({signatureName})", + _ => throw new Exception("Unknown transfer type for parameter with a null terminated platform string array") + }; + + if (parameter.Parameter.Nullable) + createExpression = $"{signatureName} is null ? {Model.PlatformStringArray.GetInternalUnownedHandleName()}.NullHandle : {createExpression}"; + + var expressionType = parameter.Parameter switch + { + { Transfer: GirModel.Transfer.Full } => Model.PlatformStringArray.GetInternalUnownedHandleName(), + { Transfer: GirModel.Transfer.None } => Model.PlatformStringArray.GetInternalHandleName(), + _ => throw new Exception("Unknown transfer type for parameter with a null terminated input platform string array") + }; + + parameter.SetSignatureName(signatureName); + parameter.SetCallName(nativeVariableName); + parameter.SetExpression($"{expressionType} {nativeVariableName} = {createExpression};"); + } + + private static void NullTerminatedArrayOut(ParameterToNativeData parameter) + { + var signatureName = Model.Parameter.GetName(parameter.Parameter); + var nativeVariableName = signatureName + "Native"; + + var createExpression = parameter.Parameter switch + { + { Transfer: GirModel.Transfer.Full } => $"{nativeVariableName}.ConvertToStringArray()", + { Transfer: GirModel.Transfer.None } => $"{nativeVariableName}.ConvertToStringArray()", + { Transfer: GirModel.Transfer.Container } => $"{nativeVariableName}.ConvertToStringArray()", + _ => throw new Exception("Unknown transfer type for parameter with a null terminated output platform string array") + }; + + if (!parameter.Parameter.Nullable) + createExpression += " ?? throw new System.Exception(\"Unexpected null value\")"; + + parameter.SetSignatureName(signatureName); + parameter.SetCallName($"out var {nativeVariableName}"); + parameter.SetPostCallExpression($"{signatureName} = {createExpression};"); + } + + private static void SizeBasedArray(ParameterToNativeData parameter) + { + if (parameter.Parameter.Direction != GirModel.Direction.In) + throw new NotImplementedException($"{parameter.Parameter.AnyTypeOrVarArgs}: Platform string array type with direction != in not yet supported"); + + //We don't need any conversion for string[] + var variableName = Model.Parameter.GetName(parameter.Parameter); + parameter.SetSignatureName(variableName); + parameter.SetCallName(variableName); + } +} diff --git a/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/Converter/StringArray.cs b/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/Converter/StringArray.cs deleted file mode 100644 index 3e74225d3..000000000 --- a/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/Converter/StringArray.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Collections.Generic; -using Generator.Model; - -namespace Generator.Renderer.Public.ParameterToNativeExpressions; - -internal class StringArray : ToNativeParameterConverter -{ - public bool Supports(GirModel.AnyType type) - => type.IsArray(); - - public void Initialize(ParameterToNativeData parameter, IEnumerable _) - { - if (parameter.Parameter.Direction != GirModel.Direction.In) - throw new NotImplementedException($"{parameter.Parameter.AnyTypeOrVarArgs}: String array type with direction != in not yet supported"); - - var arrayType = parameter.Parameter.AnyTypeOrVarArgs.AsT0.AsT1; - if (parameter.Parameter.Transfer == GirModel.Transfer.None && arrayType.Length == null) - { - var variableName = Model.Parameter.GetName(parameter.Parameter); - var nativeVariableName = variableName + "Native"; - - parameter.SetSignatureName(variableName); - parameter.SetCallName(nativeVariableName); - parameter.SetExpression($"var {nativeVariableName} = new GLib.Internal.StringArrayNullTerminatedSafeHandle({variableName}).DangerousGetHandle();"); - } - else - { - //We don't need any conversion for string[] - var variableName = Model.Parameter.GetName(parameter.Parameter); - parameter.SetSignatureName(variableName); - parameter.SetCallName(variableName); - } - } -} diff --git a/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/Converter/Utf8StringArray.cs b/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/Converter/Utf8StringArray.cs new file mode 100644 index 000000000..4658bcbc5 --- /dev/null +++ b/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/Converter/Utf8StringArray.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; + +namespace Generator.Renderer.Public.ParameterToNativeExpressions; + +internal class Utf8StringArray : ToNativeParameterConverter +{ + public bool Supports(GirModel.AnyType type) + => type.IsArray(); + + public void Initialize(ParameterToNativeData parameter, IEnumerable _) + { + var arrayType = parameter.Parameter.AnyTypeOrVarArgs.AsT0.AsT1; + if (arrayType.Length is null) + NullTerminatedArray(parameter); + else + SizeBasedArray(parameter); + } + + private static void NullTerminatedArray(ParameterToNativeData parameter) + { + switch (parameter.Parameter.Direction) + { + case GirModel.Direction.In: + NullTerminatedArrayIn(parameter); + break; + case GirModel.Direction.Out: + NullTerminatedArrayOut(parameter); + break; + default: + throw new Exception($"Unsupported direction {parameter.Parameter.Direction} for utf8 string array."); + } + } + + private static void NullTerminatedArrayIn(ParameterToNativeData parameter) + { + var signatureName = Model.Parameter.GetName(parameter.Parameter); + var nativeVariableName = signatureName + "Native"; + + var createExpression = parameter.Parameter switch + { + { Transfer: GirModel.Transfer.Full } => $"{Model.Utf8StringArray.GetInternalUnownedHandleName()}.Create({signatureName})", + { Transfer: GirModel.Transfer.None } => $"{Model.Utf8StringArray.GetInternalOwnedHandleName()}.Create({signatureName})", + _ => throw new Exception("Unknown transfer type for parameter with a null terminated input utf8 string array") + }; + + if (parameter.Parameter.Nullable) + createExpression = $"{signatureName} is null ? {Model.Utf8StringArray.GetInternalUnownedHandleName()}.NullHandle : {createExpression}"; + + var expressionType = parameter.Parameter switch + { + { Transfer: GirModel.Transfer.Full } => Model.Utf8StringArray.GetInternalUnownedHandleName(), + { Transfer: GirModel.Transfer.None } => Model.Utf8StringArray.GetInternalHandleName(), + _ => throw new Exception("Unknown transfer type for parameter with a null terminated input utf8 string array") + }; + + parameter.SetSignatureName(signatureName); + parameter.SetCallName(nativeVariableName); + parameter.SetExpression($"{expressionType} {nativeVariableName} = {createExpression};"); + } + + private static void NullTerminatedArrayOut(ParameterToNativeData parameter) + { + var signatureName = Model.Parameter.GetName(parameter.Parameter); + var nativeVariableName = signatureName + "Native"; + + var createExpression = parameter.Parameter switch + { + { Transfer: GirModel.Transfer.Full } => $"{nativeVariableName}.ConvertToStringArray()", + { Transfer: GirModel.Transfer.None } => $"{nativeVariableName}.ConvertToStringArray()", + { Transfer: GirModel.Transfer.Container } => $"{nativeVariableName}.ConvertToStringArray()", + _ => throw new Exception("Unknown transfer type for parameter with a null terminated output utf8 string array") + }; + + if (!parameter.Parameter.Nullable) + createExpression += " ?? throw new System.Exception(\"Unexpected null value\")"; + + parameter.SetSignatureName(signatureName); + parameter.SetCallName($"out var {nativeVariableName}"); + parameter.SetPostCallExpression($"{signatureName} = {createExpression};"); + } + + private static void SizeBasedArray(ParameterToNativeData parameter) + { + if (parameter.Parameter.Direction != GirModel.Direction.In) + throw new NotImplementedException($"{parameter.Parameter.AnyTypeOrVarArgs}: Utf8 string array type with direction != in not yet supported"); + + //We don't need any conversion for string[] + var variableName = Model.Parameter.GetName(parameter.Parameter); + parameter.SetSignatureName(variableName); + parameter.SetCallName(variableName); + } +} diff --git a/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/ParameterToNativeExpression.cs b/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/ParameterToNativeExpression.cs index 02a845ae8..b31eeac8e 100644 --- a/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/ParameterToNativeExpression.cs +++ b/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/ParameterToNativeExpression.cs @@ -18,6 +18,7 @@ internal static class ParameterToNativeExpression new ParameterToNativeExpressions.OpaqueTypedRecord(), new ParameterToNativeExpressions.OpaqueTypedRecordArray(), new ParameterToNativeExpressions.PlatformString(), + new ParameterToNativeExpressions.PlatformStringArray(), new ParameterToNativeExpressions.Pointer(), new ParameterToNativeExpressions.PointerAlias(), new ParameterToNativeExpressions.PrimitiveValueType(), @@ -25,8 +26,8 @@ internal static class ParameterToNativeExpression new ParameterToNativeExpressions.PrimitiveValueTypeArray(), new ParameterToNativeExpressions.Record(), new ParameterToNativeExpressions.RecordArray(), - new ParameterToNativeExpressions.StringArray(), new ParameterToNativeExpressions.Utf8String(), + new ParameterToNativeExpressions.Utf8StringArray(), }; public static IReadOnlyList Initialize(IEnumerable parameters) diff --git a/src/Generation/Generator/Renderer/Public/ReturnType/Converter/StringArray.cs b/src/Generation/Generator/Renderer/Public/ReturnType/Converter/StringArray.cs index 84b59d172..d2bd6da51 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnType/Converter/StringArray.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnType/Converter/StringArray.cs @@ -6,7 +6,7 @@ internal class StringArray : ReturnTypeConverter { public RenderableReturnType Create(GirModel.ReturnType returnType) { - return new RenderableReturnType(ArrayType.GetName(returnType.AnyType.AsT1)); + return new RenderableReturnType(ArrayType.GetName(returnType.AnyType.AsT1) + Nullable.Render(returnType)); } public bool Supports(GirModel.ReturnType returnType) diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PlatformStringArray.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PlatformStringArray.cs new file mode 100644 index 000000000..099c75650 --- /dev/null +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PlatformStringArray.cs @@ -0,0 +1,27 @@ +namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; + +internal class PlatformStringArray : ReturnTypeConverter +{ + public bool Supports(GirModel.AnyType type) + => type.IsArray(); + + public string GetString(GirModel.ReturnType returnType, string fromVariableName) + { + if (returnType.AnyType.AsT1.Length == null) + return NullTerminatedArray(returnType, fromVariableName); + else + return SizeBasedArray(returnType, fromVariableName); + } + + private static string NullTerminatedArray(GirModel.ReturnType returnType, string fromVariableName) + { + return returnType.Nullable + ? $"{fromVariableName}.ConvertToStringArray()" + : $"{fromVariableName}.ConvertToStringArray() ?? throw new System.Exception(\"Unexpected null value\")"; + } + + private static string SizeBasedArray(GirModel.ReturnType returnType, string fromVariableName) + { + return fromVariableName; + } +} diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/StringArray.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/StringArray.cs deleted file mode 100644 index 2442c3fe1..000000000 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/StringArray.cs +++ /dev/null @@ -1,16 +0,0 @@ -using GirModel; - -namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; - -internal class StringArray : ReturnTypeConverter -{ - public bool Supports(AnyType type) - => type.IsArray(); - - public string GetString(GirModel.ReturnType returnType, string fromVariableName) - { - return returnType.Transfer == Transfer.None && returnType.AnyType.AsT1.Length == null - ? $"GLib.Internal.StringHelper.ToStringArrayUtf8({fromVariableName})" //variableName is a pointer to a string array - : fromVariableName; //variableName is a string[] - } -} diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Utf8StringArray.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Utf8StringArray.cs new file mode 100644 index 000000000..062728f1c --- /dev/null +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Utf8StringArray.cs @@ -0,0 +1,27 @@ +namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; + +internal class Utf8StringArray : ReturnTypeConverter +{ + public bool Supports(GirModel.AnyType type) + => type.IsArray(); + + public string GetString(GirModel.ReturnType returnType, string fromVariableName) + { + if (returnType.AnyType.AsT1.Length == null) + return NullTerminatedArray(returnType, fromVariableName); + else + return SizeBasedArray(returnType, fromVariableName); + } + + private static string NullTerminatedArray(GirModel.ReturnType returnType, string fromVariableName) + { + return returnType.Nullable + ? $"{fromVariableName}.ConvertToStringArray()" + : $"{fromVariableName}.ConvertToStringArray() ?? throw new System.Exception(\"Unexpected null value\")"; + } + + private static string SizeBasedArray(GirModel.ReturnType returnType, string fromVariableName) + { + return fromVariableName; + } +} diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/ReturnTypeToManagedExpression.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/ReturnTypeToManagedExpression.cs index 6422df0e9..f03a03ef5 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/ReturnTypeToManagedExpression.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/ReturnTypeToManagedExpression.cs @@ -12,14 +12,15 @@ internal static class ReturnTypeToManagedExpression new ReturnTypeToManagedExpressions.Interface(), new ReturnTypeToManagedExpressions.OpaqueTypedRecord(), new ReturnTypeToManagedExpressions.PlatformString(), + new ReturnTypeToManagedExpressions.PlatformStringArray(), new ReturnTypeToManagedExpressions.Pointer(), new ReturnTypeToManagedExpressions.PointerAlias(), new ReturnTypeToManagedExpressions.PrimitiveValueType(), new ReturnTypeToManagedExpressions.PrimitiveValueTypeAlias(), new ReturnTypeToManagedExpressions.PrimitiveValueTypeArray(), new ReturnTypeToManagedExpressions.Record(), - new ReturnTypeToManagedExpressions.StringArray(), new ReturnTypeToManagedExpressions.Utf8String(), + new ReturnTypeToManagedExpressions.Utf8StringArray(), }; public static string Render(GirModel.ReturnType from, string fromVariableName) diff --git a/src/Libs/GLib-2.0/Internal/PlatformStringArrayNullTerminatedHandle.cs b/src/Libs/GLib-2.0/Internal/PlatformStringArrayNullTerminatedHandle.cs new file mode 100644 index 000000000..d79a2c82c --- /dev/null +++ b/src/Libs/GLib-2.0/Internal/PlatformStringArrayNullTerminatedHandle.cs @@ -0,0 +1,182 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; +using GObject.Internal; + +namespace GLib.Internal; + +public abstract class PlatformStringArrayNullTerminatedHandle : SafeHandle +{ + [DllImport(ImportResolver.Library, EntryPoint = "g_filename_to_utf8")] + internal static extern IntPtr FilenameToUtf8(IntPtr opsysstring, long len, out nuint bytesRead, out nuint bytesWritten, out ErrorOwnedHandle error); + + [DllImport(ImportResolver.Library, EntryPoint = "g_filename_from_utf8")] + internal static extern IntPtr FilenameFromUtf8(IntPtr utf8string, long len, out nuint bytesRead, out nuint bytesWritten, out ErrorOwnedHandle error); + + protected PlatformStringArrayNullTerminatedHandle(bool ownsHandle) : base(IntPtr.Zero, ownsHandle) + { + } + + protected static IntPtr ToIntPtr(string[] array) + { + var data = Functions.Malloc((uint) ((array.Length + 1) * IntPtr.Size)); + + for (var i = 0; i < array.Length; i++) + { + var utf8Ptr = IntPtr.Zero; + + try + { + utf8Ptr = StringHelper.StringToPtrUtf8(array[i]); + var filenamePtr = FilenameFromUtf8(utf8Ptr, -1, out _, out _, out var error); + + if (!error.IsInvalid) + throw new GException(error); + + Marshal.WriteIntPtr(data, i * IntPtr.Size, filenamePtr); + } + finally + { + Functions.Free(utf8Ptr); + } + } + + //Null terminate array + Marshal.WriteIntPtr(data, array.Length * IntPtr.Size, IntPtr.Zero); + + return data; + } + + /// + /// Converts the data of this handle into a managed string array. + /// + /// A string array containing the handle data . + public string[]? ConvertToStringArray() + { + if (handle == IntPtr.Zero) + return null; + + List strArray = new(); + var offset = 0; + + while (true) + { + var strAddress = Marshal.ReadIntPtr(handle, offset++ * IntPtr.Size); + + if (strAddress == IntPtr.Zero) + break; + + var utf8Ptr = FilenameToUtf8(strAddress, -1, out _, out _, out var error); + + if (!error.IsInvalid) + throw new GException(error); + + strArray.Add(Marshal.PtrToStringUTF8(utf8Ptr) ?? string.Empty); + } + + return strArray.ToArray(); + } +} + +/// +/// A handle of a string array which is completely owned by the dotnet runtime +/// +public class PlatformStringArrayNullTerminatedOwnedHandle : PlatformStringArrayNullTerminatedHandle +{ + public override bool IsInvalid => handle == IntPtr.Zero; + + /// + /// Used by PInvoke + /// + private PlatformStringArrayNullTerminatedOwnedHandle() : base(true) + { + } + + public PlatformStringArrayNullTerminatedOwnedHandle(IntPtr ptr) : base(true) + { + SetHandle(ptr); + } + + public static PlatformStringArrayNullTerminatedOwnedHandle Create(string[] array) + { + return new PlatformStringArrayNullTerminatedOwnedHandle(ToIntPtr(array)); + } + + protected override bool ReleaseHandle() + { + var offset = 0; + while (true) + { + var strAddress = Marshal.ReadIntPtr(handle, offset++ * IntPtr.Size); + + if (strAddress == IntPtr.Zero) + break; + + Functions.Free(strAddress); + } + + Functions.Free(handle); + return true; + } +} + +/// +/// A handle of a string array. The dotnet runtime only owns the list of pointers to the string. Not the strings itself. +/// +public class PlatformStringArrayNullTerminatedContainerHandle : PlatformStringArrayNullTerminatedHandle +{ + public override bool IsInvalid => handle == IntPtr.Zero; + + /// + /// Used by PInvoke + /// + private PlatformStringArrayNullTerminatedContainerHandle() : base(true) + { + } + + public PlatformStringArrayNullTerminatedContainerHandle(IntPtr ptr) : base(true) + { + SetHandle(ptr); + } + + protected override bool ReleaseHandle() + { + //Only free the list, not the strings itself + Functions.Free(handle); + return true; + } +} + +/// +/// A handle of a string array which is not owned by the dotnet runtime. +/// +public class PlatformStringArrayNullTerminatedUnownedHandle : PlatformStringArrayNullTerminatedHandle +{ + public override bool IsInvalid => handle == IntPtr.Zero; + + private static PlatformStringArrayNullTerminatedUnownedHandle? _nullHandle; + public static PlatformStringArrayNullTerminatedUnownedHandle NullHandle => _nullHandle ??= new PlatformStringArrayNullTerminatedUnownedHandle(IntPtr.Zero); + + /// + /// Used by PInvoke + /// + private PlatformStringArrayNullTerminatedUnownedHandle() : base(false) + { + } + + public PlatformStringArrayNullTerminatedUnownedHandle(IntPtr ptr) : base(false) + { + SetHandle(ptr); + } + + public static PlatformStringArrayNullTerminatedUnownedHandle Create(string[] array) + { + return new PlatformStringArrayNullTerminatedUnownedHandle(ToIntPtr(array)); + } + + protected override bool ReleaseHandle() + { + throw new Exception("It is not allowed to free unowned string array handle"); + } +} diff --git a/src/Libs/GLib-2.0/Internal/StringHelper.cs b/src/Libs/GLib-2.0/Internal/StringHelper.cs index 75e7eb03a..5e9448720 100644 --- a/src/Libs/GLib-2.0/Internal/StringHelper.cs +++ b/src/Libs/GLib-2.0/Internal/StringHelper.cs @@ -8,52 +8,6 @@ namespace GLib.Internal; public static class StringHelper { - /// - /// Interprets the given ptr as a non nullable string. - /// - /// a managed version of the string. - /// This method does not free the unmanaged string represented by ptr. - public static string? ToStringUtf8(IntPtr ptr) - => Marshal.PtrToStringUTF8(ptr); - - /// - /// Marshals each pointer in the IntPtr array as a UTF-8 encoded string. - /// - /// - /// A managed version of the string array. - /// This method does not free the unmanaged strings represented by ptr. - public static string[] ToStringArrayUtf8(IntPtr[] ptrArray) - => ptrArray.Select(x => ToStringUtf8(x) ?? string.Empty).ToArray(); - - /// - /// Interprets the given ptr as a null terminated string array. - /// - /// A managed version of the string array. - /// This method does not free the unmanaged strings represented by ptr. - public static string[] ToStringArrayUtf8(IntPtr ptr) - { - if (ptr == IntPtr.Zero) - return System.Array.Empty(); - - // Build string array - List strArray = new(); - var offset = 0; - - while (true) - { - // Read in the next pointer in memory - IntPtr strAddress = Marshal.ReadIntPtr(ptr, offset++ * IntPtr.Size); - - // Break if we reach the end of the array - if (strAddress == IntPtr.Zero) - break; - - // Marshal string and repeat - strArray.Add(ToStringUtf8(strAddress) ?? string.Empty); - } - - return strArray.ToArray(); - } /// /// Creates a null-terminated UTF-8 string in unmanaged memory. @@ -66,7 +20,7 @@ public static IntPtr StringToPtrUtf8(string? str) return IntPtr.Zero; var bytes = Encoding.UTF8.GetBytes(str); - IntPtr alloc = Functions.Malloc((uint) (bytes.Length + 1)); + var alloc = Functions.Malloc((uint) (bytes.Length + 1)); Marshal.Copy(bytes, 0, alloc, bytes.Length); Marshal.WriteByte(alloc, bytes.Length, 0); @@ -74,49 +28,3 @@ public static IntPtr StringToPtrUtf8(string? str) } } -public class StringArrayNullTerminatedSafeHandle : SafeHandle -{ - private GCHandle _gcHandle; - private readonly IntPtr[] _data; - - public StringArrayNullTerminatedSafeHandle(string[] array) : base(IntPtr.Zero, true) - { - var numStrings = array.Length; - _data = new IntPtr[numStrings + 1]; - - // Populate with UTF-8 encoded bytes - for (var i = 0; i < numStrings; i++) - { - // Get null-terminated UTF-8 byte array - var bytes = Encoding.UTF8.GetBytes(array[i] + '\0'); - - // Marshal as pointer - IntPtr ptr = Marshal.AllocHGlobal(bytes.Length); - Marshal.Copy(bytes, 0, ptr, bytes.Length); - - // Save in data array - _data[i] = ptr; - } - - // Null terminate the array - _data[numStrings] = IntPtr.Zero; - - // Keep in memory until done - _gcHandle = GCHandle.Alloc(_data, GCHandleType.Pinned); - SetHandle(_gcHandle.AddrOfPinnedObject()); - } - - protected override bool ReleaseHandle() - { - // Free string memory - foreach (IntPtr ptr in _data) - Marshal.FreeHGlobal(ptr); - - // Allow GC to free memory - _gcHandle.Free(); - - return true; - } - - public override bool IsInvalid => !_gcHandle.IsAllocated; -} diff --git a/src/Libs/GLib-2.0/Internal/Utf8StringArrayNullTerminatedHandle.cs b/src/Libs/GLib-2.0/Internal/Utf8StringArrayNullTerminatedHandle.cs new file mode 100644 index 000000000..bde8f64ca --- /dev/null +++ b/src/Libs/GLib-2.0/Internal/Utf8StringArrayNullTerminatedHandle.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace GLib.Internal; + +public abstract class Utf8StringArrayNullTerminatedHandle : SafeHandle +{ + protected Utf8StringArrayNullTerminatedHandle(bool ownsHandle) : base(IntPtr.Zero, ownsHandle) + { + } + + protected static IntPtr ToIntPtr(string[] array) + { + var data = Functions.Malloc((uint) ((array.Length + 1) * IntPtr.Size)); + + for (var i = 0; i < array.Length; i++) + Marshal.WriteIntPtr(data, i * IntPtr.Size, StringHelper.StringToPtrUtf8(array[i])); + + //Null terminate array + Marshal.WriteIntPtr(data, array.Length * IntPtr.Size, IntPtr.Zero); + + return data; + } + + /// + /// Converts the data of this handle into a managed string array. + /// + /// A string array containing the handle data . + public string[]? ConvertToStringArray() + { + if (handle == IntPtr.Zero) + return null; + + List strArray = new(); + var offset = 0; + + while (true) + { + var strAddress = Marshal.ReadIntPtr(handle, offset++ * IntPtr.Size); + + if (strAddress == IntPtr.Zero) + break; + + strArray.Add(Marshal.PtrToStringUTF8(strAddress) ?? string.Empty); + } + + return strArray.ToArray(); + } +} + +/// +/// A handle of a string array which is completely owned by the dotnet runtime +/// +public class Utf8StringArrayNullTerminatedOwnedHandle : Utf8StringArrayNullTerminatedHandle +{ + public override bool IsInvalid => handle == IntPtr.Zero; + + /// + /// Used by PInvoke + /// + private Utf8StringArrayNullTerminatedOwnedHandle() : base(true) + { + } + + public Utf8StringArrayNullTerminatedOwnedHandle(IntPtr ptr) : base(true) + { + SetHandle(ptr); + } + + public static Utf8StringArrayNullTerminatedOwnedHandle Create(string[] array) + { + return new Utf8StringArrayNullTerminatedOwnedHandle(ToIntPtr(array)); + } + + [DllImport(ImportResolver.Library, EntryPoint = "g_strfreev")] + private static extern void StrFreeV(IntPtr strArray); + + protected override bool ReleaseHandle() + { + StrFreeV(handle); + return true; + } +} + +/// +/// A handle of a string array. The dotnet runtime only owns the list of pointers to the string. Not the strings itself. +/// +public class Utf8StringArrayNullTerminatedContainerHandle : Utf8StringArrayNullTerminatedHandle +{ + public override bool IsInvalid => handle == IntPtr.Zero; + + /// + /// Used by PInvoke + /// + private Utf8StringArrayNullTerminatedContainerHandle() : base(true) + { + } + + public Utf8StringArrayNullTerminatedContainerHandle(IntPtr ptr) : base(true) + { + SetHandle(ptr); + } + + protected override bool ReleaseHandle() + { + //Only free the list, not the strings itself + Functions.Free(handle); + return true; + } +} + +/// +/// A handle of a string array which is not owned by the dotnet runtime. +/// +public class Utf8StringArrayNullTerminatedUnownedHandle : Utf8StringArrayNullTerminatedHandle +{ + public override bool IsInvalid => handle == IntPtr.Zero; + + private static Utf8StringArrayNullTerminatedUnownedHandle? _nullHandle; + public static Utf8StringArrayNullTerminatedUnownedHandle NullHandle => _nullHandle ??= new Utf8StringArrayNullTerminatedUnownedHandle(IntPtr.Zero); + + /// + /// Used by PInvoke + /// + private Utf8StringArrayNullTerminatedUnownedHandle() : base(false) + { + } + + public Utf8StringArrayNullTerminatedUnownedHandle(IntPtr ptr) : base(false) + { + SetHandle(ptr); + } + + public static Utf8StringArrayNullTerminatedUnownedHandle Create(string[] array) + { + return new Utf8StringArrayNullTerminatedUnownedHandle(ToIntPtr(array)); + } + + protected override bool ReleaseHandle() + { + throw new Exception("It is not allowed to free unowned string array handle"); + } +} diff --git a/src/Libs/GLib-2.0/Internal/Utf8StringHandle.cs b/src/Libs/GLib-2.0/Internal/Utf8StringHandle.cs index 0ba7f72cc..e7f513882 100644 --- a/src/Libs/GLib-2.0/Internal/Utf8StringHandle.cs +++ b/src/Libs/GLib-2.0/Internal/Utf8StringHandle.cs @@ -18,7 +18,7 @@ protected NullableUtf8StringHandle(bool ownsHandle) : base(IntPtr.Zero, ownsHand /// A string containing the handle data or null. public string? ConvertToString() { - return StringHelper.ToStringUtf8(handle); + return Marshal.PtrToStringUTF8(handle); } } @@ -94,7 +94,7 @@ public string ConvertToString() if (IsInvalid) throw new NullHandleException($"{nameof(NonNullableUtf8StringHandle)} should not have a null handle"); - return StringHelper.ToStringUtf8(handle)!; + return Marshal.PtrToStringUTF8(handle)!; } } diff --git a/src/Libs/GObject-2.0/Public/Value.cs b/src/Libs/GObject-2.0/Public/Value.cs index 1f6498ade..bc767b1a4 100644 --- a/src/Libs/GObject-2.0/Public/Value.cs +++ b/src/Libs/GObject-2.0/Public/Value.cs @@ -99,7 +99,7 @@ public void Set(object? value) // Marshalling logic happens inside this safe handle. GValue takes a // copy of the boxed memory so we do not need to keep it alive. The // Garbage Collector will automatically free the safe handle for us. - var strArray = new StringArrayNullTerminatedSafeHandle(array); + var strArray = Utf8StringArrayNullTerminatedOwnedHandle.Create(array); SetBoxed(strArray.DangerousGetHandle()); break; case GLib.Variant v: @@ -178,8 +178,11 @@ public ParamSpec GetParam() { IntPtr ptr = Internal.Value.GetBoxed(Handle); + if (ptr == IntPtr.Zero) + return null; + if (type == Internal.Functions.StrvGetType()) - return StringHelper.ToStringArrayUtf8(ptr); + return new Utf8StringArrayNullTerminatedUnownedHandle(ptr).ConvertToStringArray(); // TODO: It would be nice to support boxing arbitrary managed types // One idea for how to achieve this is creating our own 'OpaqueBoxed' type diff --git a/src/Libs/WebKit-6.0/Public/UserScript.cs b/src/Libs/WebKit-6.0/Public/UserScript.cs deleted file mode 100644 index 5bc1dfd0c..000000000 --- a/src/Libs/WebKit-6.0/Public/UserScript.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace WebKit; - -public partial class UserScript -{ - //TODO: Should be generated automatically for records - public static UserScript New(string source, UserContentInjectedFrames injectedFrames, UserScriptInjectionTime injectionTime) - { - return new UserScript(Internal.UserScript.New(GLib.Internal.NonNullableUtf8StringOwnedHandle.Create(source), injectedFrames, injectionTime, IntPtr.Zero, IntPtr.Zero)); - } -} diff --git a/src/Native/GirTestLib/girtest-platform-string-array-null-terminated-tester.c b/src/Native/GirTestLib/girtest-platform-string-array-null-terminated-tester.c new file mode 100644 index 000000000..c0e5cf662 --- /dev/null +++ b/src/Native/GirTestLib/girtest-platform-string-array-null-terminated-tester.c @@ -0,0 +1,294 @@ +#include "girtest-platform-string-array-null-terminated-tester.h" + +/** + * GirTestPlatformStringArrayNullTerminatedTester: + * + * Contains functions for testing bindings with string arrays. + */ + +struct _GirTestPlatformStringArrayNullTerminatedTester +{ + GObject parent_instance; +}; + +G_DEFINE_TYPE(GirTestPlatformStringArrayNullTerminatedTester, girtest_platform_string_array_null_terminated_tester, G_TYPE_OBJECT) + +static void +girtest_platform_string_array_null_terminated_tester_init(GirTestPlatformStringArrayNullTerminatedTester *value) +{ +} + +static void +girtest_platform_string_array_null_terminated_tester_class_init(GirTestPlatformStringArrayNullTerminatedTesterClass *class) +{ +} + +/** + * girtest_platform_string_array_null_terminated_tester_get_last_element_transfer_none: + * @data: (transfer none) (array zero-terminated=1) (element-type filename): data buffer + * + * Get's the last element of the utf8 zero terminated array + * + * Returns: (transfer none) (type filename): the last element of the array + */ +gchar* +girtest_platform_string_array_null_terminated_tester_get_last_element_transfer_none(gchar** data) +{ + guint length = g_strv_length(data); + return data[length -1]; +} + +/** + * girtest_platform_string_array_null_terminated_tester_get_last_element_transfer_full: + * @data: (transfer full) (array zero-terminated=1) (element-type filename): data buffer + * + * Get's the last element of the utf8 zero terminated array + * + * Returns: (transfer full) (type filename): the last element of the array + */ +gchar* +girtest_platform_string_array_null_terminated_tester_get_last_element_transfer_full(gchar** data) +{ + guint length = g_strv_length(data); + gchar* last_element = g_strdup(data[length -1]); + g_strfreev(data); + return last_element; +} + +/** + * girtest_platform_string_array_null_terminated_tester_get_last_element_transfer_none_nullable: + * @data: (transfer none) (array zero-terminated=1) (nullable) (element-type filename): data buffer + * + * Get's the last element of the utf8 zero terminated array or NULL + * + * Returns: (transfer none) (nullable) (type filename): the last element of the array or NULL + */ +gchar* +girtest_platform_string_array_null_terminated_tester_get_last_element_transfer_none_nullable(gchar** data) +{ + if(!data) + return NULL; + + guint length = g_strv_length(data); + return data[length -1]; +} + +/** + * girtest_platform_string_array_null_terminated_tester_get_last_element_transfer_full_nullable: + * @data: (transfer full) (array zero-terminated=1) (nullable) (element-type filename): data buffer + * + * Get's the last element of the utf8 zero terminated array or NULL + * + * Returns: (transfer full) (nullable) (type filename): the last element of the array or NULL + */ +gchar* +girtest_platform_string_array_null_terminated_tester_get_last_element_transfer_full_nullable(gchar** data) +{ + if(!data) + return NULL; + + guint length = g_strv_length(data); + gchar* last_element = g_strdup(data[length -1]); + g_strfreev(data); + return last_element; +} + +/** + * girtest_platform_string_array_null_terminated_tester_return_transfer_full: + * @data: (transfer none) (array zero-terminated=1) (element-type filename): data buffer + * + * Copies the string array and returns it + * + * Returns: (transfer full) (element-type filename): a copy of the array. + */ +gchar** +girtest_platform_string_array_null_terminated_tester_return_transfer_full(gchar** data) +{ + return g_strdupv(data); +} + +/** + * girtest_platform_string_array_null_terminated_tester_return_transfer_none: + * @data: (transfer none) (array zero-terminated=1) (element-type filename): data buffer + * + * Returns the given string array + * + * Returns: (transfer none) (element-type filename): the given string array + */ +gchar** +girtest_platform_string_array_null_terminated_tester_return_transfer_none(gchar** data) +{ + return data; +} + +/** + * girtest_platform_string_array_null_terminated_tester_return_transfer_container: + * @first: (transfer none) (type filename): First element of the array + * @second: (transfer none) (type filename): Second element of the array + * + * Returns a new array which contains elements which are not allowed to be freed. + * + * Returns: (transfer container) (element-type filename): a new array with content which is not allowed to get freed. + */ +gchar** +girtest_platform_string_array_null_terminated_tester_return_transfer_container(gchar* first, gchar* second) +{ + gchar** data = g_malloc(sizeof(gchar*) * 3); + data[0] = first; + data[1] = second; + data[2] = NULL; + + return data; +} + +/** + * girtest_platform_string_array_null_terminated_tester_return_transfer_full_nullable: + * @data: (transfer none) (array zero-terminated=1) (nullable) (element-type filename): data buffer + * + * Copies the string array and returns it. + * + * Returns: (transfer full) (nullable) (element-type filename): a copy of the array or NULL if @data is NULL. + */ +gchar** +girtest_platform_string_array_null_terminated_tester_return_transfer_full_nullable(gchar** data) +{ + return g_strdupv(data); +} + +/** + * girtest_platform_string_array_null_terminated_tester_return_transfer_none_nullable: + * @data: (transfer none) (array zero-terminated=1) (nullable) (element-type filename): data buffer + * + * Returns the given string array + * + * Returns: (transfer none) (nullable) (element-type filename): the given string array or NULL + */ +gchar** +girtest_platform_string_array_null_terminated_tester_return_transfer_none_nullable(gchar** data) +{ + return data; +} + +/** + * girtest_platform_string_array_null_terminated_tester_return_transfer_container_nullable: + * @first: (transfer none) (type filename) (nullable): First element of the array + * @second: (transfer none) (type filename) (nullable): Second element of the array + * + * Returns a new array which contains elements which are not allowed to be freed. If any of the parameters is NULL, + * NULL will be returned + * + * Returns: (transfer container) (nullable) (element-type filename): a new array with content which is not allowed to get freed or NULL + */ +gchar** +girtest_platform_string_array_null_terminated_tester_return_transfer_container_nullable(gchar* first, gchar* second) +{ + if(!first) + return NULL; + + if(!second) + return NULL; + + gchar** data = g_malloc(sizeof(gchar*) * 3); + data[0] = first; + data[1] = second; + data[2] = NULL; + + return data; +} + +/** + * girtest_platform_string_array_null_terminated_tester_parameter_out_transfer_full: + * @data: (transfer none) (array zero-terminated=1) (element-type filename): data buffer + * @output: (transfer full) (array zero-terminated=1) (out) (element-type filename): output buffer + * + * Copies the string array and returns it as output parameter + */ +void +girtest_platform_string_array_null_terminated_tester_parameter_out_transfer_full(gchar** data, gchar*** output) +{ + *output = g_strdupv(data); +} + +/** + * girtest_platform_string_array_null_terminated_tester_parameter_out_transfer_none: + * @data: (transfer none) (array zero-terminated=1) (element-type filename): data buffer + * @output: (transfer none) (array zero-terminated=1) (out) (element-type filename): output buffer + * + * Assigns @data to @output. + */ +void +girtest_platform_string_array_null_terminated_tester_parameter_out_transfer_none(gchar** data, gchar*** output) +{ + *output = data; +} + +/** + * girtest_platform_string_array_null_terminated_tester_parameter_out_transfer_container: + * @first: (transfer none) (type filename): First element of the array + * @second: (transfer none) (type filename): Second element of the array + * @output: (transfer container) (array zero-terminated=1) (out) (element-type filename): output buffer + * + * Creates a new array with content which is not allowed to get freed. + */ +void +girtest_platform_string_array_null_terminated_tester_parameter_out_transfer_container(gchar* first, gchar* second, gchar*** output) +{ + gchar** data = g_malloc(sizeof(gchar*) * 3); + data[0] = first; + data[1] = second; + data[2] = NULL; + + *output = data; +} + +/** + * girtest_platform_string_array_null_terminated_tester_parameter_out_transfer_full_nullable: + * @data: (transfer none) (array zero-terminated=1) (nullable) (element-type filename): data buffer + * @output: (transfer full) (array zero-terminated=1) (out) (nullable) (element-type filename): output buffer + * + * Copies the string array and returns it as output parameter + */ +void +girtest_platform_string_array_null_terminated_tester_parameter_out_transfer_full_nullable(gchar** data, gchar*** output) +{ + *output = g_strdupv(data); +} + +/** + * girtest_platform_string_array_null_terminated_tester_parameter_out_transfer_none_nullable: + * @data: (transfer none) (array zero-terminated=1) (nullable) (element-type filename): data buffer + * @output: (transfer none) (array zero-terminated=1) (out) (nullable) (element-type filename): output buffer + * + * Assigns @data to @output. + */ +void +girtest_platform_string_array_null_terminated_tester_parameter_out_transfer_none_nullable(gchar** data, gchar*** output) +{ + *output = data; +} + +/** + * girtest_platform_string_array_null_terminated_tester_parameter_out_transfer_container_nullable: + * @first: (transfer none) (type filename) (nullable): First element of the array + * @second: (transfer none) (type filename) (nullable): Second element of the array + * @output: (transfer container) (array zero-terminated=1) (out) (nullable) (element-type filename): output buffer + * + * Creates a new array with content which is not allowed to get freed. If @first or @second is NULL *output will be NULL. + */ +void +girtest_platform_string_array_null_terminated_tester_parameter_out_transfer_container_nullable(gchar* first, gchar* second, gchar*** output) +{ + if(!first || !second) + { + *output = NULL; + } + else + { + gchar** data = g_malloc(sizeof(gchar*) * 3); + data[0] = first; + data[1] = second; + data[2] = NULL; + + *output = data; + } +} \ No newline at end of file diff --git a/src/Native/GirTestLib/girtest-platform-string-array-null-terminated-tester.h b/src/Native/GirTestLib/girtest-platform-string-array-null-terminated-tester.h new file mode 100644 index 000000000..7b9737725 --- /dev/null +++ b/src/Native/GirTestLib/girtest-platform-string-array-null-terminated-tester.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +G_BEGIN_DECLS + +#define GIRTEST_TYPE_PLATFORM_STRING_ARRAY_NULL_TERMINATED_TESTER girtest_platform_string_array_null_terminated_tester_get_type() + +G_DECLARE_FINAL_TYPE(GirTestPlatformStringArrayNullTerminatedTester, girtest_platform_string_array_null_terminated_tester, + GIRTEST, PLATFORM_STRING_ARRAY_NULL_TERMINATED_TESTER, GObject) + +gchar* girtest_platform_string_array_null_terminated_tester_get_last_element_transfer_none(gchar** data); +gchar* girtest_platform_string_array_null_terminated_tester_get_last_element_transfer_full(gchar** data); +gchar* girtest_platform_string_array_null_terminated_tester_get_last_element_transfer_none_nullable(gchar** data); +gchar* girtest_platform_string_array_null_terminated_tester_get_last_element_transfer_full_nullable(gchar** data); +gchar** girtest_platform_string_array_null_terminated_tester_return_transfer_full(gchar** data); +gchar** girtest_platform_string_array_null_terminated_tester_return_transfer_none(gchar** data); +gchar** girtest_platform_string_array_null_terminated_tester_return_transfer_container(gchar* first, gchar* second); +gchar** girtest_platform_string_array_null_terminated_tester_return_transfer_full_nullable(gchar** data); +gchar** girtest_platform_string_array_null_terminated_tester_return_transfer_none_nullable(gchar** data); +gchar** girtest_platform_string_array_null_terminated_tester_return_transfer_container_nullable(gchar* first, gchar* second); +void girtest_platform_string_array_null_terminated_tester_parameter_out_transfer_full(gchar** data, gchar*** output); +void girtest_platform_string_array_null_terminated_tester_parameter_out_transfer_none(gchar** data, gchar*** output); +void girtest_platform_string_array_null_terminated_tester_parameter_out_transfer_container(gchar* first, gchar* second, gchar*** output); +void girtest_platform_string_array_null_terminated_tester_parameter_out_transfer_full_nullable(gchar** data, gchar*** output); +void girtest_platform_string_array_null_terminated_tester_parameter_out_transfer_none_nullable(gchar** data, gchar*** output); +void girtest_platform_string_array_null_terminated_tester_parameter_out_transfer_container_nullable(gchar* first, gchar* second, gchar*** output); + +G_END_DECLS diff --git a/src/Native/GirTestLib/girtest-utf8-string-array-null-terminated-tester.c b/src/Native/GirTestLib/girtest-utf8-string-array-null-terminated-tester.c new file mode 100644 index 000000000..3793362a9 --- /dev/null +++ b/src/Native/GirTestLib/girtest-utf8-string-array-null-terminated-tester.c @@ -0,0 +1,294 @@ +#include "girtest-utf8-string-array-null-terminated-tester.h" + +/** + * GirTestUtf8StringArrayNullTerminatedTester: + * + * Contains functions for testing bindings with string arrays. + */ + +struct _GirTestUtf8StringArrayNullTerminatedTester +{ + GObject parent_instance; +}; + +G_DEFINE_TYPE(GirTestUtf8StringArrayNullTerminatedTester, girtest_utf8_string_array_null_terminated_tester, G_TYPE_OBJECT) + +static void +girtest_utf8_string_array_null_terminated_tester_init(GirTestUtf8StringArrayNullTerminatedTester *value) +{ +} + +static void +girtest_utf8_string_array_null_terminated_tester_class_init(GirTestUtf8StringArrayNullTerminatedTesterClass *class) +{ +} + +/** + * girtest_utf8_string_array_null_terminated_tester_get_last_element_transfer_none: + * @data: (transfer none) (array zero-terminated=1): data buffer + * + * Get's the last element of the utf8 zero terminated array + * + * Returns: (transfer none): the last element of the array + */ +gchar* +girtest_utf8_string_array_null_terminated_tester_get_last_element_transfer_none(gchar** data) +{ + guint length = g_strv_length(data); + return data[length -1]; +} + +/** + * girtest_utf8_string_array_null_terminated_tester_get_last_element_transfer_full: + * @data: (transfer full) (array zero-terminated=1): data buffer + * + * Get's the last element of the utf8 zero terminated array + * + * Returns: (transfer full): the last element of the array + */ +gchar* +girtest_utf8_string_array_null_terminated_tester_get_last_element_transfer_full(gchar** data) +{ + guint length = g_strv_length(data); + gchar* last_element = g_strdup(data[length -1]); + g_strfreev(data); + return last_element; +} + +/** + * girtest_utf8_string_array_null_terminated_tester_get_last_element_transfer_none_nullable: + * @data: (transfer none) (array zero-terminated=1) (nullable): data buffer + * + * Get's the last element of the utf8 zero terminated array or NULL + * + * Returns: (transfer none) (nullable): the last element of the array or NULL + */ +gchar* +girtest_utf8_string_array_null_terminated_tester_get_last_element_transfer_none_nullable(gchar** data) +{ + if(!data) + return NULL; + + guint length = g_strv_length(data); + return data[length -1]; +} + +/** + * girtest_utf8_string_array_null_terminated_tester_get_last_element_transfer_full_nullable: + * @data: (transfer full) (array zero-terminated=1) (nullable): data buffer + * + * Get's the last element of the utf8 zero terminated array or NULL + * + * Returns: (transfer full) (nullable): the last element of the array or NULL + */ +gchar* +girtest_utf8_string_array_null_terminated_tester_get_last_element_transfer_full_nullable(gchar** data) +{ + if(!data) + return NULL; + + guint length = g_strv_length(data); + gchar* last_element = g_strdup(data[length -1]); + g_strfreev(data); + return last_element; +} + +/** + * girtest_utf8_string_array_null_terminated_tester_return_transfer_full: + * @data: (transfer none) (array zero-terminated=1): data buffer + * + * Copies the string array and returns it + * + * Returns: (transfer full): a copy of the array. + */ +gchar** +girtest_utf8_string_array_null_terminated_tester_return_transfer_full(gchar** data) +{ + return g_strdupv(data); +} + +/** + * girtest_utf8_string_array_null_terminated_tester_return_transfer_none: + * @data: (transfer none) (array zero-terminated=1): data buffer + * + * Returns the given string array + * + * Returns: (transfer none): the given string array + */ +gchar** +girtest_utf8_string_array_null_terminated_tester_return_transfer_none(gchar** data) +{ + return data; +} + +/** + * girtest_utf8_string_array_null_terminated_tester_return_transfer_container: + * @first: (transfer none): First element of the array + * @second: (transfer none): Second element of the array + * + * Returns a new array which contains elements which are not allowed to be freed. + * + * Returns: (transfer container): a new array with content which is not allowed to get freed. + */ +gchar** +girtest_utf8_string_array_null_terminated_tester_return_transfer_container(gchar* first, gchar* second) +{ + gchar** data = g_malloc(sizeof(gchar*) * 3); + data[0] = first; + data[1] = second; + data[2] = NULL; + + return data; +} + +/** + * girtest_utf8_string_array_null_terminated_tester_return_transfer_full_nullable: + * @data: (transfer none) (array zero-terminated=1) (nullable): data buffer + * + * Copies the string array and returns it. + * + * Returns: (transfer full) (nullable): a copy of the array or NULL if @data is NULL. + */ +gchar** +girtest_utf8_string_array_null_terminated_tester_return_transfer_full_nullable(gchar** data) +{ + return g_strdupv(data); +} + +/** + * girtest_utf8_string_array_null_terminated_tester_return_transfer_none_nullable: + * @data: (transfer none) (array zero-terminated=1) (nullable): data buffer + * + * Returns the given string array + * + * Returns: (transfer none) (nullable): the given string array or NULL + */ +gchar** +girtest_utf8_string_array_null_terminated_tester_return_transfer_none_nullable(gchar** data) +{ + return data; +} + +/** + * girtest_utf8_string_array_null_terminated_tester_return_transfer_container_nullable: + * @first: (transfer none) (nullable): First element of the array + * @second: (transfer none) (nullable): Second element of the array + * + * Returns a new array which contains elements which are not allowed to be freed. If any of the parameters is NULL, + * NULL will be returned + * + * Returns: (transfer container) (nullable): a new array with content which is not allowed to get freed or NULL + */ +gchar** +girtest_utf8_string_array_null_terminated_tester_return_transfer_container_nullable(gchar* first, gchar* second) +{ + if(!first) + return NULL; + + if(!second) + return NULL; + + gchar** data = g_malloc(sizeof(gchar*) * 3); + data[0] = first; + data[1] = second; + data[2] = NULL; + + return data; +} + +/** + * girtest_utf8_string_array_null_terminated_tester_parameter_out_transfer_full: + * @data: (transfer none) (array zero-terminated=1): data buffer + * @output: (transfer full) (array zero-terminated=1) (out): output buffer + * + * Copies the string array and returns it as output parameter + */ +void +girtest_utf8_string_array_null_terminated_tester_parameter_out_transfer_full(gchar** data, gchar*** output) +{ + *output = g_strdupv(data); +} + +/** + * girtest_utf8_string_array_null_terminated_tester_parameter_out_transfer_none: + * @data: (transfer none) (array zero-terminated=1): data buffer + * @output: (transfer none) (array zero-terminated=1) (out): output buffer + * + * Assigns @data to @output. + */ +void +girtest_utf8_string_array_null_terminated_tester_parameter_out_transfer_none(gchar** data, gchar*** output) +{ + *output = data; +} + +/** + * girtest_utf8_string_array_null_terminated_tester_parameter_out_transfer_container: + * @first: (transfer none): First element of the array + * @second: (transfer none): Second element of the array + * @output: (transfer container) (array zero-terminated=1) (out): output buffer + * + * Creates a new array with content which is not allowed to get freed. + */ +void +girtest_utf8_string_array_null_terminated_tester_parameter_out_transfer_container(gchar* first, gchar* second, gchar*** output) +{ + gchar** data = g_malloc(sizeof(gchar*) * 3); + data[0] = first; + data[1] = second; + data[2] = NULL; + + *output = data; +} + +/** + * girtest_utf8_string_array_null_terminated_tester_parameter_out_transfer_full_nullable: + * @data: (transfer none) (array zero-terminated=1) (nullable): data buffer + * @output: (transfer full) (array zero-terminated=1) (out) (nullable): output buffer + * + * Copies the string array and returns it as output parameter + */ +void +girtest_utf8_string_array_null_terminated_tester_parameter_out_transfer_full_nullable(gchar** data, gchar*** output) +{ + *output = g_strdupv(data); +} + +/** + * girtest_utf8_string_array_null_terminated_tester_parameter_out_transfer_none_nullable: + * @data: (transfer none) (array zero-terminated=1) (nullable): data buffer + * @output: (transfer none) (array zero-terminated=1) (out) (nullable): output buffer + * + * Assigns @data to @output. + */ +void +girtest_utf8_string_array_null_terminated_tester_parameter_out_transfer_none_nullable(gchar** data, gchar*** output) +{ + *output = data; +} + +/** + * girtest_utf8_string_array_null_terminated_tester_parameter_out_transfer_container_nullable: + * @first: (transfer none) (nullable): First element of the array + * @second: (transfer none) (nullable): Second element of the array + * @output: (transfer container) (array zero-terminated=1) (out) (nullable): output buffer + * + * Creates a new array with content which is not allowed to get freed. If @first or @second is NULL *output will be NULL. + */ +void +girtest_utf8_string_array_null_terminated_tester_parameter_out_transfer_container_nullable(gchar* first, gchar* second, gchar*** output) +{ + if(!first || !second) + { + *output = NULL; + } + else + { + gchar** data = g_malloc(sizeof(gchar*) * 3); + data[0] = first; + data[1] = second; + data[2] = NULL; + + *output = data; + } +} \ No newline at end of file diff --git a/src/Native/GirTestLib/girtest-utf8-string-array-null-terminated-tester.h b/src/Native/GirTestLib/girtest-utf8-string-array-null-terminated-tester.h new file mode 100644 index 000000000..5423c0859 --- /dev/null +++ b/src/Native/GirTestLib/girtest-utf8-string-array-null-terminated-tester.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +G_BEGIN_DECLS + +#define GIRTEST_TYPE_UTF8_STRING_ARRAY_NULL_TERMINATED_TESTER girtest_utf8_string_array_null_terminated_tester_get_type() + +G_DECLARE_FINAL_TYPE(GirTestUtf8StringArrayNullTerminatedTester, girtest_utf8_string_array_null_terminated_tester, + GIRTEST, UTF8_STRING_ARRAY_NULL_TERMINATED_TESTER, GObject) + +gchar* girtest_utf8_string_array_null_terminated_tester_get_last_element_transfer_none(gchar** data); +gchar* girtest_utf8_string_array_null_terminated_tester_get_last_element_transfer_full(gchar** data); +gchar* girtest_utf8_string_array_null_terminated_tester_get_last_element_transfer_none_nullable(gchar** data); +gchar* girtest_utf8_string_array_null_terminated_tester_get_last_element_transfer_full_nullable(gchar** data); +gchar** girtest_utf8_string_array_null_terminated_tester_return_transfer_full(gchar** data); +gchar** girtest_utf8_string_array_null_terminated_tester_return_transfer_none(gchar** data); +gchar** girtest_utf8_string_array_null_terminated_tester_return_transfer_container(gchar* first, gchar* second); +gchar** girtest_utf8_string_array_null_terminated_tester_return_transfer_full_nullable(gchar** data); +gchar** girtest_utf8_string_array_null_terminated_tester_return_transfer_none_nullable(gchar** data); +gchar** girtest_utf8_string_array_null_terminated_tester_return_transfer_container_nullable(gchar* first, gchar* second); +void girtest_utf8_string_array_null_terminated_tester_parameter_out_transfer_full(gchar** data, gchar*** output); +void girtest_utf8_string_array_null_terminated_tester_parameter_out_transfer_none(gchar** data, gchar*** output); +void girtest_utf8_string_array_null_terminated_tester_parameter_out_transfer_container(gchar* first, gchar* second, gchar*** output); +void girtest_utf8_string_array_null_terminated_tester_parameter_out_transfer_full_nullable(gchar** data, gchar*** output); +void girtest_utf8_string_array_null_terminated_tester_parameter_out_transfer_none_nullable(gchar** data, gchar*** output); +void girtest_utf8_string_array_null_terminated_tester_parameter_out_transfer_container_nullable(gchar* first, gchar* second, gchar*** output); + +G_END_DECLS diff --git a/src/Native/GirTestLib/girtest.h b/src/Native/GirTestLib/girtest.h index 93713ede7..117979e2e 100644 --- a/src/Native/GirTestLib/girtest.h +++ b/src/Native/GirTestLib/girtest.h @@ -10,6 +10,7 @@ #include "girtest-error-tester.h" #include "girtest-integer-array-tester.h" #include "girtest-opaque-typed-record-tester.h" +#include "girtest-platform-string-array-null-terminated-tester.h" #include "girtest-primitive-value-type-tester.h" #include "girtest-property-tester.h" #include "girtest-record-tester.h" @@ -17,5 +18,6 @@ #include "girtest-returning-signal-tester.h" #include "girtest-signal-tester.h" #include "girtest-string-tester.h" +#include "girtest-utf8-string-array-null-terminated-tester.h" #include "data/girtest-executor.h" #include "data/girtest-executor-impl.h" diff --git a/src/Native/GirTestLib/meson.build b/src/Native/GirTestLib/meson.build index a57d2c0e6..1f68edb71 100644 --- a/src/Native/GirTestLib/meson.build +++ b/src/Native/GirTestLib/meson.build @@ -13,6 +13,7 @@ header_files = [ 'girtest-error-tester.h', 'girtest-integer-array-tester.h', 'girtest-opaque-typed-record-tester.h', + 'girtest-platform-string-array-null-terminated-tester.h', 'girtest-primitive-value-type-tester.h', 'girtest-property-tester.h', 'girtest-record-tester.h', @@ -20,6 +21,7 @@ header_files = [ 'girtest-returning-signal-tester.h', 'girtest-signal-tester.h', 'girtest-string-tester.h', + 'girtest-utf8-string-array-null-terminated-tester.h', 'data/girtest-executor.h', 'data/girtest-executor-impl.h', ] @@ -33,6 +35,7 @@ source_files = [ 'girtest-error-tester.c', 'girtest-integer-array-tester.c', 'girtest-opaque-typed-record-tester.c', + 'girtest-platform-string-array-null-terminated-tester.c', 'girtest-primitive-value-type-tester.c', 'girtest-property-tester.c', 'girtest-record-tester.c', @@ -40,6 +43,7 @@ source_files = [ 'girtest-returning-signal-tester.c', 'girtest-signal-tester.c', 'girtest-string-tester.c', + 'girtest-utf8-string-array-null-terminated-tester.c', 'data/girtest-executor.c', 'data/girtest-executor-impl.c', ] diff --git a/src/Samples/WebKit-6.0/JavascriptCall/Program.cs b/src/Samples/WebKit-6.0/JavascriptCall/Program.cs index 80bed2d69..3e8d14d03 100644 --- a/src/Samples/WebKit-6.0/JavascriptCall/Program.cs +++ b/src/Samples/WebKit-6.0/JavascriptCall/Program.cs @@ -13,7 +13,9 @@ ucm.AddScript(WebKit.UserScript.New( source: "function testFunc() { return 'Success' }", injectedFrames: WebKit.UserContentInjectedFrames.AllFrames, - injectionTime: WebKit.UserScriptInjectionTime.End) + injectionTime: WebKit.UserScriptInjectionTime.End, + allowList: null, + blockList: null) ); webView.OnLoadChanged += async (view, signalArgs) => diff --git a/src/Samples/WebKit-6.0/JavascriptCallback/Program.cs b/src/Samples/WebKit-6.0/JavascriptCallback/Program.cs index 93775c408..f1d527dee 100644 --- a/src/Samples/WebKit-6.0/JavascriptCallback/Program.cs +++ b/src/Samples/WebKit-6.0/JavascriptCallback/Program.cs @@ -20,7 +20,9 @@ })(this) """, injectedFrames: WebKit.UserContentInjectedFrames.AllFrames, - injectionTime: WebKit.UserScriptInjectionTime.End) + injectionTime: WebKit.UserScriptInjectionTime.End, + allowList: null, + blockList: null) ); WebKit.UserContentManager.ScriptMessageReceivedSignal.Connect(ucm, (manager, signalArgs) => diff --git a/src/Tests/Libs/GirTest-0.1.Tests/PlatformStringArrayNullTerminatedTest.cs b/src/Tests/Libs/GirTest-0.1.Tests/PlatformStringArrayNullTerminatedTest.cs new file mode 100644 index 000000000..02e13fbbf --- /dev/null +++ b/src/Tests/Libs/GirTest-0.1.Tests/PlatformStringArrayNullTerminatedTest.cs @@ -0,0 +1,190 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace GirTest.Tests; + +[TestClass, TestCategory("BindingTest")] +public class PlatformStringArrayNullTerminated : Test +{ + [TestMethod] + public void SupportsParameterTransferNone() + { + var data = new[] { "Str1", "Str2" }; + var result = PlatformStringArrayNullTerminatedTester.GetLastElementTransferNone(data); + + result.Should().Be(data[1]); + } + + [TestMethod] + public void SupportsParameterTransferFull() + { + var data = new[] { "Str1", "Str2" }; + var result = PlatformStringArrayNullTerminatedTester.GetLastElementTransferFull(data); + + result.Should().Be(data[1]); + } + + [TestMethod] + public void SupportsParameterTransferNoneNullable() + { + var data = new[] { "Str1", "Str2" }; + var result = PlatformStringArrayNullTerminatedTester.GetLastElementTransferNoneNullable(data); + result.Should().Be(data[1]); + + result = PlatformStringArrayNullTerminatedTester.GetLastElementTransferNoneNullable(null); + result.Should().BeNull(); + } + + [TestMethod] + public void SupportsParameterTransferFullNullable() + { + var data = new[] { "Str1", "Str2" }; + var result = PlatformStringArrayNullTerminatedTester.GetLastElementTransferFullNullable(data); + result.Should().Be(data[1]); + + result = PlatformStringArrayNullTerminatedTester.GetLastElementTransferFullNullable(null); + result.Should().BeNull(); + } + + [TestMethod] + public void SupportsReturnTransferFull() + { + var data = new[] { "Str1", "Str2" }; + var result = PlatformStringArrayNullTerminatedTester.ReturnTransferFull(data); + + result[0].Should().Be(data[0]); + result[1].Should().Be(data[1]); + result.Length.Should().Be(2); + } + + [TestMethod] + public void SupportsReturnTransferNone() + { + var data = new[] { "Str1", "Str2" }; + var result = PlatformStringArrayNullTerminatedTester.ReturnTransferNone(data); + + result[0].Should().Be(data[0]); + result[1].Should().Be(data[1]); + result.Length.Should().Be(2); + } + + [TestMethod] + public void SupportsReturnTransferContainer() + { + var result = PlatformStringArrayNullTerminatedTester.ReturnTransferContainer("foo", "bar"); + + result[0].Should().Be("foo"); + result[1].Should().Be("bar"); + result.Length.Should().Be(2); + } + + [TestMethod] + public void SupportsReturnTransferFullNullable() + { + var data = new[] { "Str1", "Str2" }; + var result = PlatformStringArrayNullTerminatedTester.ReturnTransferFullNullable(data); + result![0].Should().Be(data[0]); + result[1].Should().Be(data[1]); + result.Length.Should().Be(2); + + result = PlatformStringArrayNullTerminatedTester.ReturnTransferFullNullable(null); + result.Should().BeNull(); + } + + [TestMethod] + public void SupportsReturnTransferNoneNullable() + { + var data = new[] { "Str1", "Str2" }; + var result = PlatformStringArrayNullTerminatedTester.ReturnTransferNoneNullable(data); + + result![0].Should().Be(data[0]); + result[1].Should().Be(data[1]); + result.Length.Should().Be(2); + + result = PlatformStringArrayNullTerminatedTester.ReturnTransferNoneNullable(null); + result.Should().BeNull(); + } + + [TestMethod] + public void SupportsReturnTransferContainerNullable() + { + var result = PlatformStringArrayNullTerminatedTester.ReturnTransferContainerNullable("foo", "bar"); + + result![0].Should().Be("foo"); + result[1].Should().Be("bar"); + result.Length.Should().Be(2); + + result = PlatformStringArrayNullTerminatedTester.ReturnTransferContainerNullable(null, null); + result.Should().BeNull(); + } + + [TestMethod] + public void SupportsParameterOutputTransferFull() + { + var data = new[] { "Str1", "Str2" }; + PlatformStringArrayNullTerminatedTester.ParameterOutTransferFull(data, out var result); + + result[0].Should().Be(data[0]); + result[1].Should().Be(data[1]); + result.Length.Should().Be(2); + } + + [TestMethod] + public void SupportsParameterOutputTransferNone() + { + var data = new[] { "Str1", "Str2" }; + PlatformStringArrayNullTerminatedTester.ParameterOutTransferNone(data, out var result); + + result[0].Should().Be(data[0]); + result[1].Should().Be(data[1]); + result.Length.Should().Be(2); + } + + [TestMethod] + public void SupportsParameterOutputTransferContainer() + { + PlatformStringArrayNullTerminatedTester.ParameterOutTransferContainer("foo", "bar", out var result); + + result[0].Should().Be("foo"); + result[1].Should().Be("bar"); + result.Length.Should().Be(2); + } + + [TestMethod] + public void SupportsParameterOutputTransferFullNullable() + { + var data = new[] { "Str1", "Str2" }; + PlatformStringArrayNullTerminatedTester.ParameterOutTransferFullNullable(data, out var result); + result![0].Should().Be(data[0]); + result[1].Should().Be(data[1]); + result.Length.Should().Be(2); + + PlatformStringArrayNullTerminatedTester.ParameterOutTransferFullNullable(null, out var result2); + result2.Should().BeNull(); + } + + [TestMethod] + public void SupportsParameterOutputTransferNoneNullable() + { + var data = new[] { "Str1", "Str2" }; + PlatformStringArrayNullTerminatedTester.ParameterOutTransferNoneNullable(data, out var result); + result![0].Should().Be(data[0]); + result[1].Should().Be(data[1]); + result.Length.Should().Be(2); + + PlatformStringArrayNullTerminatedTester.ParameterOutTransferNoneNullable(null, out var result2); + result2.Should().BeNull(); + } + + [TestMethod] + public void SupportsParameterOutputTransferContainerNullable() + { + PlatformStringArrayNullTerminatedTester.ParameterOutTransferContainerNullable("foo", "bar", out var result); + result![0].Should().Be("foo"); + result[1].Should().Be("bar"); + result.Length.Should().Be(2); + + PlatformStringArrayNullTerminatedTester.ParameterOutTransferContainerNullable(null, null, out var result2); + result2.Should().BeNull(); + } +} diff --git a/src/Tests/Libs/GirTest-0.1.Tests/Utf8StringArrayNullTerminatedTest.cs b/src/Tests/Libs/GirTest-0.1.Tests/Utf8StringArrayNullTerminatedTest.cs new file mode 100644 index 000000000..c8082d30e --- /dev/null +++ b/src/Tests/Libs/GirTest-0.1.Tests/Utf8StringArrayNullTerminatedTest.cs @@ -0,0 +1,190 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace GirTest.Tests; + +[TestClass, TestCategory("BindingTest")] +public class Utf8StringArrayNullTerminated : Test +{ + [TestMethod] + public void SupportsParameterTransferNone() + { + var data = new[] { "Str1", "Str2" }; + var result = Utf8StringArrayNullTerminatedTester.GetLastElementTransferNone(data); + + result.Should().Be(data[1]); + } + + [TestMethod] + public void SupportsParameterTransferFull() + { + var data = new[] { "Str1", "Str2" }; + var result = Utf8StringArrayNullTerminatedTester.GetLastElementTransferFull(data); + + result.Should().Be(data[1]); + } + + [TestMethod] + public void SupportsParameterTransferNoneNullable() + { + var data = new[] { "Str1", "Str2" }; + var result = Utf8StringArrayNullTerminatedTester.GetLastElementTransferNoneNullable(data); + result.Should().Be(data[1]); + + result = Utf8StringArrayNullTerminatedTester.GetLastElementTransferNoneNullable(null); + result.Should().BeNull(); + } + + [TestMethod] + public void SupportsParameterTransferFullNullable() + { + var data = new[] { "Str1", "Str2" }; + var result = Utf8StringArrayNullTerminatedTester.GetLastElementTransferFullNullable(data); + result.Should().Be(data[1]); + + result = Utf8StringArrayNullTerminatedTester.GetLastElementTransferFullNullable(null); + result.Should().BeNull(); + } + + [TestMethod] + public void SupportsReturnTransferFull() + { + var data = new[] { "Str1", "Str2" }; + var result = Utf8StringArrayNullTerminatedTester.ReturnTransferFull(data); + + result[0].Should().Be(data[0]); + result[1].Should().Be(data[1]); + result.Length.Should().Be(2); + } + + [TestMethod] + public void SupportsReturnTransferNone() + { + var data = new[] { "Str1", "Str2" }; + var result = Utf8StringArrayNullTerminatedTester.ReturnTransferNone(data); + + result[0].Should().Be(data[0]); + result[1].Should().Be(data[1]); + result.Length.Should().Be(2); + } + + [TestMethod] + public void SupportsReturnTransferContainer() + { + var result = Utf8StringArrayNullTerminatedTester.ReturnTransferContainer("foo", "bar"); + + result[0].Should().Be("foo"); + result[1].Should().Be("bar"); + result.Length.Should().Be(2); + } + + [TestMethod] + public void SupportsReturnTransferFullNullable() + { + var data = new[] { "Str1", "Str2" }; + var result = Utf8StringArrayNullTerminatedTester.ReturnTransferFullNullable(data); + result![0].Should().Be(data[0]); + result[1].Should().Be(data[1]); + result.Length.Should().Be(2); + + result = Utf8StringArrayNullTerminatedTester.ReturnTransferFullNullable(null); + result.Should().BeNull(); + } + + [TestMethod] + public void SupportsReturnTransferNoneNullable() + { + var data = new[] { "Str1", "Str2" }; + var result = Utf8StringArrayNullTerminatedTester.ReturnTransferNoneNullable(data); + + result![0].Should().Be(data[0]); + result[1].Should().Be(data[1]); + result.Length.Should().Be(2); + + result = Utf8StringArrayNullTerminatedTester.ReturnTransferNoneNullable(null); + result.Should().BeNull(); + } + + [TestMethod] + public void SupportsReturnTransferContainerNullable() + { + var result = Utf8StringArrayNullTerminatedTester.ReturnTransferContainerNullable("foo", "bar"); + + result![0].Should().Be("foo"); + result[1].Should().Be("bar"); + result.Length.Should().Be(2); + + result = Utf8StringArrayNullTerminatedTester.ReturnTransferContainerNullable(null, null); + result.Should().BeNull(); + } + + [TestMethod] + public void SupportsParameterOutputTransferFull() + { + var data = new[] { "Str1", "Str2" }; + Utf8StringArrayNullTerminatedTester.ParameterOutTransferFull(data, out var result); + + result[0].Should().Be(data[0]); + result[1].Should().Be(data[1]); + result.Length.Should().Be(2); + } + + [TestMethod] + public void SupportsParameterOutputTransferNone() + { + var data = new[] { "Str1", "Str2" }; + Utf8StringArrayNullTerminatedTester.ParameterOutTransferNone(data, out var result); + + result[0].Should().Be(data[0]); + result[1].Should().Be(data[1]); + result.Length.Should().Be(2); + } + + [TestMethod] + public void SupportsParameterOutputTransferContainer() + { + Utf8StringArrayNullTerminatedTester.ParameterOutTransferContainer("foo", "bar", out var result); + + result[0].Should().Be("foo"); + result[1].Should().Be("bar"); + result.Length.Should().Be(2); + } + + [TestMethod] + public void SupportsParameterOutputTransferFullNullable() + { + var data = new[] { "Str1", "Str2" }; + Utf8StringArrayNullTerminatedTester.ParameterOutTransferFullNullable(data, out var result); + result![0].Should().Be(data[0]); + result[1].Should().Be(data[1]); + result.Length.Should().Be(2); + + Utf8StringArrayNullTerminatedTester.ParameterOutTransferFullNullable(null, out var result2); + result2.Should().BeNull(); + } + + [TestMethod] + public void SupportsParameterOutputTransferNoneNullable() + { + var data = new[] { "Str1", "Str2" }; + Utf8StringArrayNullTerminatedTester.ParameterOutTransferNoneNullable(data, out var result); + result![0].Should().Be(data[0]); + result[1].Should().Be(data[1]); + result.Length.Should().Be(2); + + Utf8StringArrayNullTerminatedTester.ParameterOutTransferNoneNullable(null, out var result2); + result2.Should().BeNull(); + } + + [TestMethod] + public void SupportsParameterOutputTransferContainerNullable() + { + Utf8StringArrayNullTerminatedTester.ParameterOutTransferContainerNullable("foo", "bar", out var result); + result![0].Should().Be("foo"); + result[1].Should().Be("bar"); + result.Length.Should().Be(2); + + Utf8StringArrayNullTerminatedTester.ParameterOutTransferContainerNullable(null, null, out var result2); + result2.Should().BeNull(); + } +}