diff --git a/MEOS.NET.Tests/CountedArrayTests.cs b/MEOS.NET.Tests/CountedArrayTests.cs new file mode 100644 index 0000000..bc9eeac --- /dev/null +++ b/MEOS.NET.Tests/CountedArrayTests.cs @@ -0,0 +1,54 @@ +using MEOS.NET.Enums; +using MEOS.NET.Types; + +namespace MEOS.NET.Tests +{ + /// + /// MEOS reads an array of its own values through a pointer to the first + /// element and a count, so a method taking one takes a C# array and answers + /// its length to MEOS. + /// + [TestClass] + public class CountedArrayTests : MeosTest + { + [TestMethod] + public void ASequenceIsMadeOfItsInstants() + { + Temporal[] instants = + [ + TFloat.In("25.0@2024-12-06")!, + TFloat.In("27.0@2024-12-07")!, + TFloat.In("30.0@2024-12-09")!, + ]; + + Temporal sequence = TSequence.Make(instants, true, true, InterpType.Linear, true)!; + + Assert.AreEqual(3, sequence.NumInstants()); + Assert.AreEqual( + "[25@2024-12-06 00:00:00+00, 27@2024-12-07 00:00:00+00, 30@2024-12-09 00:00:00+00]", + sequence.ToString()); + } + + [TestMethod] + public void MergingAnArrayOfTemporalValuesJoinsThem() + { + Temporal[] parts = + [ + TFloat.In("[25.0@2024-12-06, 27.0@2024-12-07]")!, + TFloat.In("[30.0@2024-12-09, 32.0@2024-12-10]")!, + ]; + + Temporal merged = Temporal.MergeArray(parts)!; + + Assert.AreEqual(4, merged.NumInstants()); + Assert.AreEqual(2, merged.NumSequences()); + } + + [TestMethod] + public void AnEmptyArrayIsARequestMeosRefuses() + { + Assert.ThrowsException( + () => TSequence.Make([], true, true, InterpType.Linear, true)); + } + } +} diff --git a/MEOS.NET.Tests/OutParameterTests.cs b/MEOS.NET.Tests/OutParameterTests.cs new file mode 100644 index 0000000..c80285d --- /dev/null +++ b/MEOS.NET.Tests/OutParameterTests.cs @@ -0,0 +1,53 @@ +using MEOS.NET.Types; + +namespace MEOS.NET.Tests +{ + /// + /// MEOS answers some values through an out-parameter and returns whether the + /// value exists at all, so those methods answer the value or null. + /// + [TestClass] + public class OutParameterTests : MeosTest + { + [TestMethod] + public void ABoxAnswersTheBoundsItHas() + { + TBox box = TBox.In("TBOXFLOAT XT([1.0, 3.0],[2024-12-06, 2024-12-08])")!; + + Assert.AreEqual(1.0, box.Xmin()); + Assert.AreEqual(3.0, box.Xmax()); + Assert.AreEqual(true, box.TminInc()); + } + + [TestMethod] + public void ABoxAnswersNullForABoundItDoesNotHave() + { + TBox box = TBox.In("TBOX T([2024-12-06, 2024-12-08])")!; + + Assert.IsNull(box.Xmin()); + Assert.IsNull(box.Xmax()); + Assert.IsNotNull(box.TminInc()); + } + + [TestMethod] + public void ASetAnswersTheValueAtAnIndex() + { + Set set = FloatSet.In("{1.5, 2.5, 3.5}")!; + + Assert.AreEqual(1.5, ((FloatSet)set).ValueN(1)); + Assert.AreEqual(3.5, ((FloatSet)set).ValueN(3)); + Assert.IsNull(((FloatSet)set).ValueN(4)); + } + + [TestMethod] + public void ATemporalFloatAnswersItsValueAtAMoment() + { + TFloat temp = (TFloat)TFloat.In("[25.0@2024-12-06, 27.0@2024-12-08]")!; + + Assert.AreEqual(25.0, + temp.ValueAtTimestamptz(new DateTime(2024, 12, 6, 0, 0, 0, DateTimeKind.Utc), true)); + Assert.IsNull( + temp.ValueAtTimestamptz(new DateTime(2024, 12, 9, 0, 0, 0, DateTimeKind.Utc), true)); + } + } +} diff --git a/MEOS.NET/Types/BigIntSet.g.cs b/MEOS.NET/Types/BigIntSet.g.cs index c2cbf30..f797ccb 100644 --- a/MEOS.NET/Types/BigIntSet.g.cs +++ b/MEOS.NET/Types/BigIntSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; @@ -27,6 +29,24 @@ public string Out() public long StartValue() => Meos.BigintsetStartValue(this.Ptr); + public long? ValueN(int n) + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.BigintsetValueN(this.Ptr, n, _result)) + { + return null; + } + + return Marshal.ReadInt64(_result); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + public long[] Values() => Meos.BigintsetValues(this.Ptr); diff --git a/MEOS.NET/Types/BigIntSpan.g.cs b/MEOS.NET/Types/BigIntSpan.g.cs index 16bf168..bc3c38e 100644 --- a/MEOS.NET/Types/BigIntSpan.g.cs +++ b/MEOS.NET/Types/BigIntSpan.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/BigIntSpanSet.g.cs b/MEOS.NET/Types/BigIntSpanSet.g.cs index 50aa718..73c6e84 100644 --- a/MEOS.NET/Types/BigIntSpanSet.g.cs +++ b/MEOS.NET/Types/BigIntSpanSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/Box.g.cs b/MEOS.NET/Types/Box.g.cs index cd06e96..4147bb6 100644 --- a/MEOS.NET/Types/Box.g.cs +++ b/MEOS.NET/Types/Box.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/CbufferSet.g.cs b/MEOS.NET/Types/CbufferSet.g.cs index 52cf06f..755bbbe 100644 --- a/MEOS.NET/Types/CbufferSet.g.cs +++ b/MEOS.NET/Types/CbufferSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/Collection.g.cs b/MEOS.NET/Types/Collection.g.cs index 6b65e5b..7ffd7cc 100644 --- a/MEOS.NET/Types/Collection.g.cs +++ b/MEOS.NET/Types/Collection.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/DateSet.g.cs b/MEOS.NET/Types/DateSet.g.cs index 81b5c43..978f4d0 100644 --- a/MEOS.NET/Types/DateSet.g.cs +++ b/MEOS.NET/Types/DateSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; @@ -30,6 +32,24 @@ public DateOnly StartValue() public Set? ToTstzset() => MEOSFactory.WrapSet(Meos.DatesetToTstzset(this.Ptr)); + public DateOnly? ValueN(int n) + { + IntPtr _result = Marshal.AllocHGlobal(4); + try + { + if (!Meos.DatesetValueN(this.Ptr, n, _result)) + { + return null; + } + + return MEOSConvert.ToDateOnly(Marshal.ReadInt32(_result)); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + public int[] Values() => Meos.DatesetValues(this.Ptr); diff --git a/MEOS.NET/Types/DateSpan.g.cs b/MEOS.NET/Types/DateSpan.g.cs index cc95052..76d299f 100644 --- a/MEOS.NET/Types/DateSpan.g.cs +++ b/MEOS.NET/Types/DateSpan.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/DateSpanSet.g.cs b/MEOS.NET/Types/DateSpanSet.g.cs index 7b671a2..378f520 100644 --- a/MEOS.NET/Types/DateSpanSet.g.cs +++ b/MEOS.NET/Types/DateSpanSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; @@ -15,6 +17,24 @@ internal DateSpanSet(IntPtr ptr) : base(ptr) { } public override string ToString() => this.Out(); + public DateOnly? DateN(int n) + { + IntPtr _result = Marshal.AllocHGlobal(4); + try + { + if (!Meos.DatespansetDateN(this.Ptr, n, _result)) + { + return null; + } + + return MEOSConvert.ToDateOnly(Marshal.ReadInt32(_result)); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + public Set? Dates() => MEOSFactory.WrapSet(Meos.DatespansetDates(this.Ptr)); diff --git a/MEOS.NET/Types/FloatSet.g.cs b/MEOS.NET/Types/FloatSet.g.cs index be1b2fa..33edc9b 100644 --- a/MEOS.NET/Types/FloatSet.g.cs +++ b/MEOS.NET/Types/FloatSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; @@ -42,6 +44,24 @@ public double StartValue() public Set? ToIntset() => MEOSFactory.WrapSet(Meos.FloatsetToIntset(this.Ptr)); + public double? ValueN(int n) + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.FloatsetValueN(this.Ptr, n, _result)) + { + return null; + } + + return Marshal.PtrToStructure(_result); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + public double[] Values() => Meos.FloatsetValues(this.Ptr); diff --git a/MEOS.NET/Types/FloatSpan.g.cs b/MEOS.NET/Types/FloatSpan.g.cs index 75fcf5a..bba4ef0 100644 --- a/MEOS.NET/Types/FloatSpan.g.cs +++ b/MEOS.NET/Types/FloatSpan.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/FloatSpanSet.g.cs b/MEOS.NET/Types/FloatSpanSet.g.cs index 528ef1f..ea65d63 100644 --- a/MEOS.NET/Types/FloatSpanSet.g.cs +++ b/MEOS.NET/Types/FloatSpanSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/GeogSet.g.cs b/MEOS.NET/Types/GeogSet.g.cs index e37f3fe..107f2ca 100644 --- a/MEOS.NET/Types/GeogSet.g.cs +++ b/MEOS.NET/Types/GeogSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/GeomSet.g.cs b/MEOS.NET/Types/GeomSet.g.cs index 6f92b60..f091385 100644 --- a/MEOS.NET/Types/GeomSet.g.cs +++ b/MEOS.NET/Types/GeomSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/IntSet.g.cs b/MEOS.NET/Types/IntSet.g.cs index 296ffd7..9d4248e 100644 --- a/MEOS.NET/Types/IntSet.g.cs +++ b/MEOS.NET/Types/IntSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; @@ -30,6 +32,24 @@ public int StartValue() public Set? ToFloatset() => MEOSFactory.WrapSet(Meos.IntsetToFloatset(this.Ptr)); + public int? ValueN(int n) + { + IntPtr _result = Marshal.AllocHGlobal(4); + try + { + if (!Meos.IntsetValueN(this.Ptr, n, _result)) + { + return null; + } + + return Marshal.ReadInt32(_result); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + public int[] Values() => Meos.IntsetValues(this.Ptr); diff --git a/MEOS.NET/Types/IntSpan.g.cs b/MEOS.NET/Types/IntSpan.g.cs index d5682c2..13d26cf 100644 --- a/MEOS.NET/Types/IntSpan.g.cs +++ b/MEOS.NET/Types/IntSpan.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/IntSpanSet.g.cs b/MEOS.NET/Types/IntSpanSet.g.cs index 25421a4..df3fbb2 100644 --- a/MEOS.NET/Types/IntSpanSet.g.cs +++ b/MEOS.NET/Types/IntSpanSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/NpointSet.g.cs b/MEOS.NET/Types/NpointSet.g.cs index cc40491..74516e7 100644 --- a/MEOS.NET/Types/NpointSet.g.cs +++ b/MEOS.NET/Types/NpointSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/PoseSet.g.cs b/MEOS.NET/Types/PoseSet.g.cs index c11b9fc..43edda2 100644 --- a/MEOS.NET/Types/PoseSet.g.cs +++ b/MEOS.NET/Types/PoseSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/STBox.g.cs b/MEOS.NET/Types/STBox.g.cs index 1364163..115bdc3 100644 --- a/MEOS.NET/Types/STBox.g.cs +++ b/MEOS.NET/Types/STBox.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; @@ -87,6 +89,78 @@ public int SRID() public double SpatialDistance(STBox box2) => Meos.StboxSpatialDistance(this.Ptr, box2.Ptr); + public DateTime? Tmax() + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.StboxTmax(this.Ptr, _result)) + { + return null; + } + + return MEOSConvert.ToDateTime(Marshal.ReadInt64(_result)); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + + public bool? TmaxInc() + { + IntPtr _result = Marshal.AllocHGlobal(1); + try + { + if (!Meos.StboxTmaxInc(this.Ptr, _result)) + { + return null; + } + + return Marshal.ReadByte(_result) != 0; + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + + public DateTime? Tmin() + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.StboxTmin(this.Ptr, _result)) + { + return null; + } + + return MEOSConvert.ToDateTime(Marshal.ReadInt64(_result)); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + + public bool? TminInc() + { + IntPtr _result = Marshal.AllocHGlobal(1); + try + { + if (!Meos.StboxTminInc(this.Ptr, _result)) + { + return null; + } + + return Marshal.ReadByte(_result) != 0; + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + public Span? ToTstzspan() => MEOSFactory.WrapSpan(Meos.StboxToTstzspan(this.Ptr)); @@ -99,6 +173,114 @@ public double SpatialDistance(STBox box2) public double Volume() => Meos.StboxVolume(this.Ptr); + public double? Xmax() + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.StboxXmax(this.Ptr, _result)) + { + return null; + } + + return Marshal.PtrToStructure(_result); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + + public double? Xmin() + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.StboxXmin(this.Ptr, _result)) + { + return null; + } + + return Marshal.PtrToStructure(_result); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + + public double? Ymax() + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.StboxYmax(this.Ptr, _result)) + { + return null; + } + + return Marshal.PtrToStructure(_result); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + + public double? Ymin() + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.StboxYmin(this.Ptr, _result)) + { + return null; + } + + return Marshal.PtrToStructure(_result); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + + public double? Zmax() + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.StboxZmax(this.Ptr, _result)) + { + return null; + } + + return Marshal.PtrToStructure(_result); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + + public double? Zmin() + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.StboxZmin(this.Ptr, _result)) + { + return null; + } + + return Marshal.PtrToStructure(_result); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + public static STBox? FromHEXWKB(string hexwkb) => MEOSFactory.WrapSTBox(Meos.StboxFromHexwkb(hexwkb)); diff --git a/MEOS.NET/Types/Set.g.cs b/MEOS.NET/Types/Set.g.cs index 4591a62..c8b16ae 100644 --- a/MEOS.NET/Types/Set.g.cs +++ b/MEOS.NET/Types/Set.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/Span.g.cs b/MEOS.NET/Types/Span.g.cs index 4d1d016..1199e83 100644 --- a/MEOS.NET/Types/Span.g.cs +++ b/MEOS.NET/Types/Span.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/SpanSet.g.cs b/MEOS.NET/Types/SpanSet.g.cs index 0223c92..b5ed634 100644 --- a/MEOS.NET/Types/SpanSet.g.cs +++ b/MEOS.NET/Types/SpanSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TAlpha.g.cs b/MEOS.NET/Types/TAlpha.g.cs index c87c5e8..a75e539 100644 --- a/MEOS.NET/Types/TAlpha.g.cs +++ b/MEOS.NET/Types/TAlpha.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TBigint.g.cs b/MEOS.NET/Types/TBigint.g.cs index a042297..70e71d7 100644 --- a/MEOS.NET/Types/TBigint.g.cs +++ b/MEOS.NET/Types/TBigint.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; @@ -54,6 +56,42 @@ public long StartValue() public Temporal? ToTs2cell() => MEOSFactory.WrapTemporal(Meos.TbigintToTs2cell(this.Ptr)); + public long? ValueAtTimestamptz(DateTime t, bool strict) + { + IntPtr _value = Marshal.AllocHGlobal(8); + try + { + if (!Meos.TbigintValueAtTimestamptz(this.Ptr, MEOSConvert.ToTimestampTz(t), strict, _value)) + { + return null; + } + + return Marshal.ReadInt64(_value); + } + finally + { + Marshal.FreeHGlobal(_value); + } + } + + public long? ValueN(long n) + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.TbigintValueN(this.Ptr, n, _result)) + { + return null; + } + + return Marshal.ReadInt64(_result); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + public static Temporal? FromBaseTemp(long i, Temporal temp) => MEOSFactory.WrapTemporal(Meos.TbigintFromBaseTemp(i, temp.Ptr)); diff --git a/MEOS.NET/Types/TBigintInst.g.cs b/MEOS.NET/Types/TBigintInst.g.cs index 53f7416..402640c 100644 --- a/MEOS.NET/Types/TBigintInst.g.cs +++ b/MEOS.NET/Types/TBigintInst.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TBigintSeq.g.cs b/MEOS.NET/Types/TBigintSeq.g.cs index eb92b2b..0c8c5bc 100644 --- a/MEOS.NET/Types/TBigintSeq.g.cs +++ b/MEOS.NET/Types/TBigintSeq.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TBigintSeqSet.g.cs b/MEOS.NET/Types/TBigintSeqSet.g.cs index 1c0a8a8..d5f271f 100644 --- a/MEOS.NET/Types/TBigintSeqSet.g.cs +++ b/MEOS.NET/Types/TBigintSeqSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TBool.g.cs b/MEOS.NET/Types/TBool.g.cs index 64d2b27..9777500 100644 --- a/MEOS.NET/Types/TBool.g.cs +++ b/MEOS.NET/Types/TBool.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; @@ -33,6 +35,42 @@ public bool StartValue() public Temporal? ToTint() => MEOSFactory.WrapTemporal(Meos.TboolToTint(this.Ptr)); + public bool? ValueAtTimestamptz(DateTime t, bool strict) + { + IntPtr _value = Marshal.AllocHGlobal(1); + try + { + if (!Meos.TboolValueAtTimestamptz(this.Ptr, MEOSConvert.ToTimestampTz(t), strict, _value)) + { + return null; + } + + return Marshal.ReadByte(_value) != 0; + } + finally + { + Marshal.FreeHGlobal(_value); + } + } + + public bool? ValueN(int n) + { + IntPtr _result = Marshal.AllocHGlobal(1); + try + { + if (!Meos.TboolValueN(this.Ptr, n, _result)) + { + return null; + } + + return Marshal.ReadByte(_result) != 0; + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + public SpanSet? WhenTrue() => MEOSFactory.WrapSpanSet(Meos.TboolWhenTrue(this.Ptr)); diff --git a/MEOS.NET/Types/TBoolInst.g.cs b/MEOS.NET/Types/TBoolInst.g.cs index 3a14e5a..3f7d07c 100644 --- a/MEOS.NET/Types/TBoolInst.g.cs +++ b/MEOS.NET/Types/TBoolInst.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TBoolSeq.g.cs b/MEOS.NET/Types/TBoolSeq.g.cs index dcc7129..c3d0456 100644 --- a/MEOS.NET/Types/TBoolSeq.g.cs +++ b/MEOS.NET/Types/TBoolSeq.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TBoolSeqSet.g.cs b/MEOS.NET/Types/TBoolSeqSet.g.cs index 73c8520..22dabc6 100644 --- a/MEOS.NET/Types/TBoolSeqSet.g.cs +++ b/MEOS.NET/Types/TBoolSeqSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TBox.g.cs b/MEOS.NET/Types/TBox.g.cs index d7e3c17..d8dd6ce 100644 --- a/MEOS.NET/Types/TBox.g.cs +++ b/MEOS.NET/Types/TBox.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; @@ -57,6 +59,78 @@ public string Out(int maxdd) public TBox? Round(int maxdd) => MEOSFactory.WrapTBox(Meos.TboxRound(this.Ptr, maxdd)); + public DateTime? Tmax() + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.TboxTmax(this.Ptr, _result)) + { + return null; + } + + return MEOSConvert.ToDateTime(Marshal.ReadInt64(_result)); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + + public bool? TmaxInc() + { + IntPtr _result = Marshal.AllocHGlobal(1); + try + { + if (!Meos.TboxTmaxInc(this.Ptr, _result)) + { + return null; + } + + return Marshal.ReadByte(_result) != 0; + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + + public DateTime? Tmin() + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.TboxTmin(this.Ptr, _result)) + { + return null; + } + + return MEOSConvert.ToDateTime(Marshal.ReadInt64(_result)); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + + public bool? TminInc() + { + IntPtr _result = Marshal.AllocHGlobal(1); + try + { + if (!Meos.TboxTminInc(this.Ptr, _result)) + { + return null; + } + + return Marshal.ReadByte(_result) != 0; + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + public Span? ToBigintspan() => MEOSFactory.WrapSpan(Meos.TboxToBigintspan(this.Ptr)); @@ -69,6 +143,78 @@ public string Out(int maxdd) public Span? ToTstzspan() => MEOSFactory.WrapSpan(Meos.TboxToTstzspan(this.Ptr)); + public double? Xmax() + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.TboxXmax(this.Ptr, _result)) + { + return null; + } + + return Marshal.PtrToStructure(_result); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + + public bool? XmaxInc() + { + IntPtr _result = Marshal.AllocHGlobal(1); + try + { + if (!Meos.TboxXmaxInc(this.Ptr, _result)) + { + return null; + } + + return Marshal.ReadByte(_result) != 0; + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + + public double? Xmin() + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.TboxXmin(this.Ptr, _result)) + { + return null; + } + + return Marshal.PtrToStructure(_result); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + + public bool? XminInc() + { + IntPtr _result = Marshal.AllocHGlobal(1); + try + { + if (!Meos.TboxXminInc(this.Ptr, _result)) + { + return null; + } + + return Marshal.ReadByte(_result) != 0; + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + public static TBox? FromHEXWKB(string hexwkb) => MEOSFactory.WrapTBox(Meos.TboxFromHexwkb(hexwkb)); diff --git a/MEOS.NET/Types/TCbuffer.g.cs b/MEOS.NET/Types/TCbuffer.g.cs index c5d3404..15fa255 100644 --- a/MEOS.NET/Types/TCbuffer.g.cs +++ b/MEOS.NET/Types/TCbuffer.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TCbufferInst.g.cs b/MEOS.NET/Types/TCbufferInst.g.cs index cfb28fb..f3e4ed3 100644 --- a/MEOS.NET/Types/TCbufferInst.g.cs +++ b/MEOS.NET/Types/TCbufferInst.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TCbufferSeq.g.cs b/MEOS.NET/Types/TCbufferSeq.g.cs index a914339..1f7edf1 100644 --- a/MEOS.NET/Types/TCbufferSeq.g.cs +++ b/MEOS.NET/Types/TCbufferSeq.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TCbufferSeqSet.g.cs b/MEOS.NET/Types/TCbufferSeqSet.g.cs index e2d07be..bafdc5b 100644 --- a/MEOS.NET/Types/TCbufferSeqSet.g.cs +++ b/MEOS.NET/Types/TCbufferSeqSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TFloat.g.cs b/MEOS.NET/Types/TFloat.g.cs index cf10297..14f7e92 100644 --- a/MEOS.NET/Types/TFloat.g.cs +++ b/MEOS.NET/Types/TFloat.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; @@ -81,12 +83,48 @@ public double StartValue() public Temporal? ToTint() => MEOSFactory.WrapTemporal(Meos.TfloatToTint(this.Ptr)); + public double? ValueAtTimestamptz(DateTime t, bool strict) + { + IntPtr _value = Marshal.AllocHGlobal(8); + try + { + if (!Meos.TfloatValueAtTimestamptz(this.Ptr, MEOSConvert.ToTimestampTz(t), strict, _value)) + { + return null; + } + + return Marshal.PtrToStructure(_value); + } + finally + { + Marshal.FreeHGlobal(_value); + } + } + public Span?[] ValueBins(double vsize, double vorigin) => MEOSFactory.WrapSpanArray(Meos.TfloatValueBins(this.Ptr, vsize, vorigin)); public TBox?[] ValueBoxes(double vsize, double vorigin) => MEOSFactory.WrapTBoxArray(Meos.TfloatValueBoxes(this.Ptr, vsize, vorigin)); + public double? ValueN(int n) + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.TfloatValueN(this.Ptr, n, _result)) + { + return null; + } + + return Marshal.PtrToStructure(_result); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + public double[] Values() => Meos.TfloatValues(this.Ptr); diff --git a/MEOS.NET/Types/TFloatInst.g.cs b/MEOS.NET/Types/TFloatInst.g.cs index 45e38fd..77ae2b9 100644 --- a/MEOS.NET/Types/TFloatInst.g.cs +++ b/MEOS.NET/Types/TFloatInst.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TFloatSeq.g.cs b/MEOS.NET/Types/TFloatSeq.g.cs index f0860ca..cbc06cb 100644 --- a/MEOS.NET/Types/TFloatSeq.g.cs +++ b/MEOS.NET/Types/TFloatSeq.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TFloatSeqSet.g.cs b/MEOS.NET/Types/TFloatSeqSet.g.cs index e8b94c9..7abe65f 100644 --- a/MEOS.NET/Types/TFloatSeqSet.g.cs +++ b/MEOS.NET/Types/TFloatSeqSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TGeo.g.cs b/MEOS.NET/Types/TGeo.g.cs index be2ce7a..b13a2d6 100644 --- a/MEOS.NET/Types/TGeo.g.cs +++ b/MEOS.NET/Types/TGeo.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TGeogPoint.g.cs b/MEOS.NET/Types/TGeogPoint.g.cs index 7000248..1cc5bdd 100644 --- a/MEOS.NET/Types/TGeogPoint.g.cs +++ b/MEOS.NET/Types/TGeogPoint.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TGeogPointInst.g.cs b/MEOS.NET/Types/TGeogPointInst.g.cs index e1e6325..bcf02c9 100644 --- a/MEOS.NET/Types/TGeogPointInst.g.cs +++ b/MEOS.NET/Types/TGeogPointInst.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TGeogPointSeq.g.cs b/MEOS.NET/Types/TGeogPointSeq.g.cs index eb4f4a7..099af6c 100644 --- a/MEOS.NET/Types/TGeogPointSeq.g.cs +++ b/MEOS.NET/Types/TGeogPointSeq.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TGeogPointSeqSet.g.cs b/MEOS.NET/Types/TGeogPointSeqSet.g.cs index 090e73e..f31d686 100644 --- a/MEOS.NET/Types/TGeogPointSeqSet.g.cs +++ b/MEOS.NET/Types/TGeogPointSeqSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TGeography.g.cs b/MEOS.NET/Types/TGeography.g.cs index 73a6594..3555fbf 100644 --- a/MEOS.NET/Types/TGeography.g.cs +++ b/MEOS.NET/Types/TGeography.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TGeographyInst.g.cs b/MEOS.NET/Types/TGeographyInst.g.cs index 23b2feb..98ea92c 100644 --- a/MEOS.NET/Types/TGeographyInst.g.cs +++ b/MEOS.NET/Types/TGeographyInst.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TGeographySeq.g.cs b/MEOS.NET/Types/TGeographySeq.g.cs index a132e8c..df793a5 100644 --- a/MEOS.NET/Types/TGeographySeq.g.cs +++ b/MEOS.NET/Types/TGeographySeq.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TGeographySeqSet.g.cs b/MEOS.NET/Types/TGeographySeqSet.g.cs index c5f1e78..7676ed3 100644 --- a/MEOS.NET/Types/TGeographySeqSet.g.cs +++ b/MEOS.NET/Types/TGeographySeqSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TGeomPoint.g.cs b/MEOS.NET/Types/TGeomPoint.g.cs index 1ad0ebf..3dd793e 100644 --- a/MEOS.NET/Types/TGeomPoint.g.cs +++ b/MEOS.NET/Types/TGeomPoint.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TGeomPointInst.g.cs b/MEOS.NET/Types/TGeomPointInst.g.cs index 8a87535..110488d 100644 --- a/MEOS.NET/Types/TGeomPointInst.g.cs +++ b/MEOS.NET/Types/TGeomPointInst.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TGeomPointSeq.g.cs b/MEOS.NET/Types/TGeomPointSeq.g.cs index 08ad3b4..8b1fd8a 100644 --- a/MEOS.NET/Types/TGeomPointSeq.g.cs +++ b/MEOS.NET/Types/TGeomPointSeq.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TGeomPointSeqSet.g.cs b/MEOS.NET/Types/TGeomPointSeqSet.g.cs index 963b109..7ba7d77 100644 --- a/MEOS.NET/Types/TGeomPointSeqSet.g.cs +++ b/MEOS.NET/Types/TGeomPointSeqSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TGeometry.g.cs b/MEOS.NET/Types/TGeometry.g.cs index f76d612..52e799d 100644 --- a/MEOS.NET/Types/TGeometry.g.cs +++ b/MEOS.NET/Types/TGeometry.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TGeometryInst.g.cs b/MEOS.NET/Types/TGeometryInst.g.cs index cfddf5e..35dc952 100644 --- a/MEOS.NET/Types/TGeometryInst.g.cs +++ b/MEOS.NET/Types/TGeometryInst.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TGeometrySeq.g.cs b/MEOS.NET/Types/TGeometrySeq.g.cs index d56fe31..20247ee 100644 --- a/MEOS.NET/Types/TGeometrySeq.g.cs +++ b/MEOS.NET/Types/TGeometrySeq.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TGeometrySeqSet.g.cs b/MEOS.NET/Types/TGeometrySeqSet.g.cs index 561585e..d0e6245 100644 --- a/MEOS.NET/Types/TGeometrySeqSet.g.cs +++ b/MEOS.NET/Types/TGeometrySeqSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TInstant.g.cs b/MEOS.NET/Types/TInstant.g.cs index 0fb49ef..1d49aff 100644 --- a/MEOS.NET/Types/TInstant.g.cs +++ b/MEOS.NET/Types/TInstant.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TInt.g.cs b/MEOS.NET/Types/TInt.g.cs index a78e0ed..3c2cc5a 100644 --- a/MEOS.NET/Types/TInt.g.cs +++ b/MEOS.NET/Types/TInt.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; @@ -51,12 +53,48 @@ public int StartValue() public Temporal? ToTfloat() => MEOSFactory.WrapTemporal(Meos.TintToTfloat(this.Ptr)); + public int? ValueAtTimestamptz(DateTime t, bool strict) + { + IntPtr _value = Marshal.AllocHGlobal(4); + try + { + if (!Meos.TintValueAtTimestamptz(this.Ptr, MEOSConvert.ToTimestampTz(t), strict, _value)) + { + return null; + } + + return Marshal.ReadInt32(_value); + } + finally + { + Marshal.FreeHGlobal(_value); + } + } + public Span?[] ValueBins(int vsize, int vorigin) => MEOSFactory.WrapSpanArray(Meos.TintValueBins(this.Ptr, vsize, vorigin)); public TBox?[] ValueBoxes(int vsize, int vorigin) => MEOSFactory.WrapTBoxArray(Meos.TintValueBoxes(this.Ptr, vsize, vorigin)); + public int? ValueN(int n) + { + IntPtr _result = Marshal.AllocHGlobal(4); + try + { + if (!Meos.TintValueN(this.Ptr, n, _result)) + { + return null; + } + + return Marshal.ReadInt32(_result); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + public int[] Values() => Meos.TintValues(this.Ptr); diff --git a/MEOS.NET/Types/TIntInst.g.cs b/MEOS.NET/Types/TIntInst.g.cs index d734142..273085d 100644 --- a/MEOS.NET/Types/TIntInst.g.cs +++ b/MEOS.NET/Types/TIntInst.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TIntSeq.g.cs b/MEOS.NET/Types/TIntSeq.g.cs index 1ab09dd..c6bb2d2 100644 --- a/MEOS.NET/Types/TIntSeq.g.cs +++ b/MEOS.NET/Types/TIntSeq.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TIntSeqSet.g.cs b/MEOS.NET/Types/TIntSeqSet.g.cs index 35dfc94..11731a0 100644 --- a/MEOS.NET/Types/TIntSeqSet.g.cs +++ b/MEOS.NET/Types/TIntSeqSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TJsonb.g.cs b/MEOS.NET/Types/TJsonb.g.cs index d5cde93..239c88c 100644 --- a/MEOS.NET/Types/TJsonb.g.cs +++ b/MEOS.NET/Types/TJsonb.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TJsonbInst.g.cs b/MEOS.NET/Types/TJsonbInst.g.cs index 05487af..89399af 100644 --- a/MEOS.NET/Types/TJsonbInst.g.cs +++ b/MEOS.NET/Types/TJsonbInst.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TJsonbSeq.g.cs b/MEOS.NET/Types/TJsonbSeq.g.cs index 1358209..1e9271b 100644 --- a/MEOS.NET/Types/TJsonbSeq.g.cs +++ b/MEOS.NET/Types/TJsonbSeq.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TJsonbSeqSet.g.cs b/MEOS.NET/Types/TJsonbSeqSet.g.cs index fdbf680..0589ea4 100644 --- a/MEOS.NET/Types/TJsonbSeqSet.g.cs +++ b/MEOS.NET/Types/TJsonbSeqSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TNpoint.g.cs b/MEOS.NET/Types/TNpoint.g.cs index 5581560..c2ed0db 100644 --- a/MEOS.NET/Types/TNpoint.g.cs +++ b/MEOS.NET/Types/TNpoint.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TNpointInst.g.cs b/MEOS.NET/Types/TNpointInst.g.cs index 31ed367..b167a0b 100644 --- a/MEOS.NET/Types/TNpointInst.g.cs +++ b/MEOS.NET/Types/TNpointInst.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TNpointSeq.g.cs b/MEOS.NET/Types/TNpointSeq.g.cs index e945b60..3b560b0 100644 --- a/MEOS.NET/Types/TNpointSeq.g.cs +++ b/MEOS.NET/Types/TNpointSeq.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TNpointSeqSet.g.cs b/MEOS.NET/Types/TNpointSeqSet.g.cs index 3715e3c..3722161 100644 --- a/MEOS.NET/Types/TNpointSeqSet.g.cs +++ b/MEOS.NET/Types/TNpointSeqSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TNumber.g.cs b/MEOS.NET/Types/TNumber.g.cs index 29f83b1..9e1534a 100644 --- a/MEOS.NET/Types/TNumber.g.cs +++ b/MEOS.NET/Types/TNumber.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TPoint.g.cs b/MEOS.NET/Types/TPoint.g.cs index b9a6118..035955c 100644 --- a/MEOS.NET/Types/TPoint.g.cs +++ b/MEOS.NET/Types/TPoint.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; @@ -23,6 +25,24 @@ internal TPoint(IntPtr ptr) : base(ptr) { } public Temporal? CumulativeLength() => MEOSFactory.WrapTemporal(Meos.TpointCumulativeLength(this.Ptr)); + public double? Direction() + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.TpointDirection(this.Ptr, _result)) + { + return null; + } + + return Marshal.PtrToStructure(_result); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + public Temporal? GetX() => MEOSFactory.WrapTemporal(Meos.TpointGetX(this.Ptr)); diff --git a/MEOS.NET/Types/TPose.g.cs b/MEOS.NET/Types/TPose.g.cs index 076af2e..ae53a5e 100644 --- a/MEOS.NET/Types/TPose.g.cs +++ b/MEOS.NET/Types/TPose.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TPoseInst.g.cs b/MEOS.NET/Types/TPoseInst.g.cs index 8d5e5e3..3c7213e 100644 --- a/MEOS.NET/Types/TPoseInst.g.cs +++ b/MEOS.NET/Types/TPoseInst.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TPoseSeq.g.cs b/MEOS.NET/Types/TPoseSeq.g.cs index 88aa0bf..1f70f9a 100644 --- a/MEOS.NET/Types/TPoseSeq.g.cs +++ b/MEOS.NET/Types/TPoseSeq.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TPoseSeqSet.g.cs b/MEOS.NET/Types/TPoseSeqSet.g.cs index 79e348e..cb5b373 100644 --- a/MEOS.NET/Types/TPoseSeqSet.g.cs +++ b/MEOS.NET/Types/TPoseSeqSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TRGeometry.g.cs b/MEOS.NET/Types/TRGeometry.g.cs index 0eaa6f5..f4c44fa 100644 --- a/MEOS.NET/Types/TRGeometry.g.cs +++ b/MEOS.NET/Types/TRGeometry.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; @@ -192,5 +194,24 @@ public string Out() public static Temporal? In(string str) => MEOSFactory.WrapTemporal(Meos.TrgeometryIn(str)); + public new static Temporal? MergeArray(Temporal[] temparr) + { + IntPtr[] _temparrValues = new IntPtr[temparr.Length]; + for (int i = 0; i < temparr.Length; i++) + { + _temparrValues[i] = temparr[i].Ptr; + } + + GCHandle _temparr = GCHandle.Alloc(_temparrValues, GCHandleType.Pinned); + try + { + return MEOSFactory.WrapTemporal(Meos.TrgeometryMergeArray(_temparr.AddrOfPinnedObject(), temparr.Length)); + } + finally + { + _temparr.Free(); + } + } + } } diff --git a/MEOS.NET/Types/TRGeometryInst.g.cs b/MEOS.NET/Types/TRGeometryInst.g.cs index 9432f2f..d317814 100644 --- a/MEOS.NET/Types/TRGeometryInst.g.cs +++ b/MEOS.NET/Types/TRGeometryInst.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TRGeometrySeq.g.cs b/MEOS.NET/Types/TRGeometrySeq.g.cs index 6868e48..864dea3 100644 --- a/MEOS.NET/Types/TRGeometrySeq.g.cs +++ b/MEOS.NET/Types/TRGeometrySeq.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TRGeometrySeqSet.g.cs b/MEOS.NET/Types/TRGeometrySeqSet.g.cs index 6401afb..7474e78 100644 --- a/MEOS.NET/Types/TRGeometrySeqSet.g.cs +++ b/MEOS.NET/Types/TRGeometrySeqSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TSequence.g.cs b/MEOS.NET/Types/TSequence.g.cs index 7f774f4..3793c15 100644 --- a/MEOS.NET/Types/TSequence.g.cs +++ b/MEOS.NET/Types/TSequence.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; @@ -11,5 +13,24 @@ public class TSequence : Temporal { internal TSequence(IntPtr ptr) : base(ptr) { } + public static Temporal? Make(Temporal[] instants, bool lower_inc, bool upper_inc, InterpType interp, bool normalize) + { + IntPtr[] _instantsValues = new IntPtr[instants.Length]; + for (int i = 0; i < instants.Length; i++) + { + _instantsValues[i] = instants[i].Ptr; + } + + GCHandle _instants = GCHandle.Alloc(_instantsValues, GCHandleType.Pinned); + try + { + return MEOSFactory.WrapTemporal(Meos.TsequenceMake(_instants.AddrOfPinnedObject(), instants.Length, lower_inc, upper_inc, (int) interp, normalize)); + } + finally + { + _instants.Free(); + } + } + } } diff --git a/MEOS.NET/Types/TSequenceSet.g.cs b/MEOS.NET/Types/TSequenceSet.g.cs index df0c491..876cbb4 100644 --- a/MEOS.NET/Types/TSequenceSet.g.cs +++ b/MEOS.NET/Types/TSequenceSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; @@ -11,5 +13,24 @@ public class TSequenceSet : Temporal { internal TSequenceSet(IntPtr ptr) : base(ptr) { } + public static Temporal? Make(Temporal[] sequences, bool normalize) + { + IntPtr[] _sequencesValues = new IntPtr[sequences.Length]; + for (int i = 0; i < sequences.Length; i++) + { + _sequencesValues[i] = sequences[i].Ptr; + } + + GCHandle _sequences = GCHandle.Alloc(_sequencesValues, GCHandleType.Pinned); + try + { + return MEOSFactory.WrapTemporal(Meos.TsequencesetMake(_sequences.AddrOfPinnedObject(), sequences.Length, normalize)); + } + finally + { + _sequences.Free(); + } + } + } } diff --git a/MEOS.NET/Types/TSpatial.g.cs b/MEOS.NET/Types/TSpatial.g.cs index 5a543c1..91dd7d2 100644 --- a/MEOS.NET/Types/TSpatial.g.cs +++ b/MEOS.NET/Types/TSpatial.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TText.g.cs b/MEOS.NET/Types/TText.g.cs index e7cffb2..54f98f9 100644 --- a/MEOS.NET/Types/TText.g.cs +++ b/MEOS.NET/Types/TText.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TTextInst.g.cs b/MEOS.NET/Types/TTextInst.g.cs index 5f819bb..058b79c 100644 --- a/MEOS.NET/Types/TTextInst.g.cs +++ b/MEOS.NET/Types/TTextInst.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TTextSeq.g.cs b/MEOS.NET/Types/TTextSeq.g.cs index 3fbb9d2..3dd14da 100644 --- a/MEOS.NET/Types/TTextSeq.g.cs +++ b/MEOS.NET/Types/TTextSeq.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TTextSeqSet.g.cs b/MEOS.NET/Types/TTextSeqSet.g.cs index 87e1064..546f736 100644 --- a/MEOS.NET/Types/TTextSeqSet.g.cs +++ b/MEOS.NET/Types/TTextSeqSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/Temporal.g.cs b/MEOS.NET/Types/Temporal.g.cs index 0c6e8da..351abe4 100644 --- a/MEOS.NET/Types/Temporal.g.cs +++ b/MEOS.NET/Types/Temporal.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; @@ -233,6 +235,24 @@ public DateTime StartTimestamptz() public long[] Timestamps() => Meos.TemporalTimestamps(this.Ptr); + public DateTime? TimestamptzN(int n) + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.TemporalTimestamptzN(this.Ptr, n, _result)) + { + return null; + } + + return MEOSConvert.ToDateTime(Marshal.ReadInt64(_result)); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + public Span? ToTstzspan() => MEOSFactory.WrapSpan(Meos.TemporalToTstzspan(this.Ptr)); @@ -245,5 +265,24 @@ public bool UpperInc() public static Temporal? FromHEXWKB(string hexwkb) => MEOSFactory.WrapTemporal(Meos.TemporalFromHexwkb(hexwkb)); + public static Temporal? MergeArray(Temporal[] temparr) + { + IntPtr[] _temparrValues = new IntPtr[temparr.Length]; + for (int i = 0; i < temparr.Length; i++) + { + _temparrValues[i] = temparr[i].Ptr; + } + + GCHandle _temparr = GCHandle.Alloc(_temparrValues, GCHandleType.Pinned); + try + { + return MEOSFactory.WrapTemporal(Meos.TemporalMergeArray(_temparr.AddrOfPinnedObject(), temparr.Length)); + } + finally + { + _temparr.Free(); + } + } + } } diff --git a/MEOS.NET/Types/TextSet.g.cs b/MEOS.NET/Types/TextSet.g.cs index 5343968..e4c6a32 100644 --- a/MEOS.NET/Types/TextSet.g.cs +++ b/MEOS.NET/Types/TextSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TsTzSet.g.cs b/MEOS.NET/Types/TsTzSet.g.cs index e884934..a10036b 100644 --- a/MEOS.NET/Types/TsTzSet.g.cs +++ b/MEOS.NET/Types/TsTzSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; @@ -30,6 +32,24 @@ public DateTime StartValue() public STBox? ToStbox() => MEOSFactory.WrapSTBox(Meos.TstzsetToStbox(this.Ptr)); + public DateTime? ValueN(int n) + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.TstzsetValueN(this.Ptr, n, _result)) + { + return null; + } + + return MEOSConvert.ToDateTime(Marshal.ReadInt64(_result)); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + public long[] Values() => Meos.TstzsetValues(this.Ptr); diff --git a/MEOS.NET/Types/TsTzSpan.g.cs b/MEOS.NET/Types/TsTzSpan.g.cs index 81d675a..834c3ec 100644 --- a/MEOS.NET/Types/TsTzSpan.g.cs +++ b/MEOS.NET/Types/TsTzSpan.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; diff --git a/MEOS.NET/Types/TsTzSpanSet.g.cs b/MEOS.NET/Types/TsTzSpanSet.g.cs index aa690a6..bfa2938 100644 --- a/MEOS.NET/Types/TsTzSpanSet.g.cs +++ b/MEOS.NET/Types/TsTzSpanSet.g.cs @@ -1,5 +1,7 @@ #nullable enable +using System.Runtime.InteropServices; + using MEOS.NET.Enums; using MEOS.NET.Functions; @@ -33,6 +35,24 @@ public DateTime StartTimestamptz() public Set? Timestamps() => MEOSFactory.WrapSet(Meos.TstzspansetTimestamps(this.Ptr)); + public DateTime? TimestamptzN(int n) + { + IntPtr _result = Marshal.AllocHGlobal(8); + try + { + if (!Meos.TstzspansetTimestamptzN(this.Ptr, n, _result)) + { + return null; + } + + return MEOSConvert.ToDateTime(Marshal.ReadInt64(_result)); + } + finally + { + Marshal.FreeHGlobal(_result); + } + } + public SpanSet? ToDatespanset() => MEOSFactory.WrapSpanSet(Meos.TstzspansetToDatespanset(this.Ptr)); diff --git a/tools/objectgen.py b/tools/objectgen.py index 9f4ef40..889a7ed 100644 --- a/tools/objectgen.py +++ b/tools/objectgen.py @@ -61,6 +61,19 @@ # The template axis: a concrete class is the product ``. SUBTYPE_SUFFIX = {"TInstant": "Inst", "TSequence": "Seq", "TSequenceSet": "SeqSet"} +# What a value out-parameter of each pointee type reads back as: the C# type, the +# bytes to allocate for it, and how to read the value MEOS wrote there. +OUT_PARAM_READERS = { + "double *": ("double", 8, "Marshal.PtrToStructure({0})"), + "float8 *": ("double", 8, "Marshal.PtrToStructure({0})"), + "bool *": ("bool", 1, "Marshal.ReadByte({0}) != 0"), + "int *": ("int", 4, "Marshal.ReadInt32({0})"), + "int32_t *": ("int", 4, "Marshal.ReadInt32({0})"), + "int64_t *": ("long", 8, "Marshal.ReadInt64({0})"), + "TimestampTz *": ("DateTime", 8, "MEOSConvert.ToDateTime(Marshal.ReadInt64({0}))"), + "DateADT *": ("DateOnly", 4, "MEOSConvert.ToDateOnly(Marshal.ReadInt32({0}))"), +} + # C types the object layer passes and returns as C# scalars, keyed by the cleaned # C spelling. Everything else is either a wrapped class pointer or deferred. PASSTHROUGH_C = { @@ -233,12 +246,17 @@ class Method: """One emitted method: its C# signature and the wrapper call behind it.""" def __init__(self, name: str, ret: str, params: list[tuple[str, str]], - body: str, static: bool): + body: str, static: bool, arrays: list[tuple[str, str]] | None = None, + out_param: tuple[str, int, str] | None = None): self.name = name self.ret = ret self.params = params self.body = body self.static = static + # (parameter name, element class) for each counted array the method takes. + self.arrays = arrays or [] + # (parameter name, bytes, reader expression) for a value out-parameter. + self.out_param = out_param class Generator: @@ -321,16 +339,22 @@ def method_for(self, cls: str, entry: dict) -> Method | None: # `T *values, int count` is MEOS's counted-array convention: the pointer is # the first element of an array, not one value, so wrapping it as one # object would hand the callee a single element and a length that lies. - raw = [p["name"] for p in f.get("params", [])] + recv_ctype = self.m.ctype.get(cls) + declared = f.get("params", []) + receiver_first = (bool(declared) + and clean(declared[0]["cType"]) == f"{recv_ctype} *") + # `T *values, int count` is MEOS's counted-array convention. The length is + # named `count`; a parameter named `n` is the INDEX of the `*_n` + # accessors, whose pointer is the receiver and no array at all. counted = set() - for i, p in enumerate(f.get("params", [])): - nxt = f["params"][i + 1] if i + 1 < len(f["params"]) else None - if (clean(p["cType"]).endswith("*") and nxt - and nxt["name"] in ("count", "n") + for i, p in enumerate(declared): + nxt = declared[i + 1] if i + 1 < len(declared) else None + if (i == 0 and receiver_first) or not clean(p["cType"]).endswith("*"): + continue + if (nxt and nxt["name"] == "count" and clean(nxt["cType"]) in ("int", "int32", "int32_t")): counted.add(codegen.csharp_param_name(p["name"])) - recv_ctype = self.m.ctype.get(cls) params = list(wrapper_params) static = True args: list[str] = [] @@ -339,6 +363,23 @@ def method_for(self, cls: str, entry: dict) -> Method | None: args.append("this.Ptr") params = params[1:] + # A `bool` return with one value out-parameter is MEOS saying whether the + # value exists: the method answers the value, or nothing. + out_params = (f.get("shape") or {}).get("outParams") or [] + result_out = None + if clean(f["returnType"]["c"]) == "bool" and len(out_params) == 1: + pointee = clean(next( + (p["cType"] for p in f.get("params", []) + if p["name"] == out_params[0]), "")) + reader = OUT_PARAM_READERS.get(pointee) + if reader: + result_out = (codegen.csharp_param_name(out_params[0]), reader) + else: + self.deferred[cls].append( + f"{oo}: the value out-parameter {out_params[0]} is a " + f"{pointee}, which has no reader") + return None + ret = self.map_return(f, wrapper_ret) if ret is None: self.deferred[cls].append( @@ -349,12 +390,40 @@ def method_for(self, cls: str, entry: dict) -> Method | None: self.deferred[cls].append(f"{oo}: neither a receiver nor a value to return") return None + # A counted array is one parameter to the caller and two to MEOS: the + # array and its length, which the array itself answers. + declared = f.get("params", []) + count_of = {} + for i, p in enumerate(declared): + if (codegen.csharp_param_name(p["name"]) in counted + and i + 1 < len(declared)): + count_of[codegen.csharp_param_name(declared[i + 1]["name"])] = \ + codegen.csharp_param_name(p["name"]) + + if result_out is not None: + ret_type = f"{result_out[1][0]}?" + ret_expr = "$" + sig: list[tuple[str, str]] = [] + arrays: list[tuple[str, str]] = [] for cs_type, pname in params: + if result_out is not None and pname == result_out[0]: + args.append(f"_{pname}") + continue + if pname in count_of: + args.append(f"{count_of[pname]}.Length") + continue if pname in counted: - self.deferred[cls].append( - f"{oo}: argument {pname} is a counted array") - return None + element = self.m.class_for_ctype(clean(c_by_name[pname])[:-1]) + if element is None: + self.deferred[cls].append( + f"{oo}: argument {pname} is an array of " + f"{clean(c_by_name[pname])[:-1]}, which has no class") + return None + sig.append((f"{element}[]", pname)) + arrays.append((pname, element)) + args.append(f"_{pname}.AddrOfPinnedObject()") + continue mapped = self.map_param(c_by_name.get(pname, ""), cs_type, pname) if mapped is None: self.deferred[cls].append( @@ -365,7 +434,12 @@ def method_for(self, cls: str, entry: dict) -> Method | None: args.append(mapped[1]) call = f"Meos.{codegen.public_name(fname)}({', '.join(args)})" - return Method(pascal(oo), ret_type, sig, ret_expr.replace("$", call), static) + out = None + if result_out is not None: + name, (_, size, reader) = result_out + out = (name, size, reader.format(f"_{name}")) + return Method(pascal(oo), ret_type, sig, ret_expr.replace("$", call), static, + arrays, out) def inherited_names(self, cls: str) -> set[tuple]: names: set[tuple] = set() @@ -393,6 +467,8 @@ def emit_class(self, cls: str) -> str: lines = [ "#nullable enable", "", + "using System.Runtime.InteropServices;", + "", "using MEOS.NET.Enums;", "using MEOS.NET.Functions;", "", @@ -411,11 +487,71 @@ def emit_class(self, cls: str) -> str: new = "new " if (m.name, tuple(t for t, _ in m.params)) in inherited else "" kind = "static " if m.static else "" lines.append(f" public {new}{kind}{m.ret} {m.name}({args})") - lines.append(f" => {m.body};") + if m.out_param: + lines.extend(self.out_param_body(m)) + elif m.arrays: + lines.extend(self.array_body(m)) + else: + lines.append(f" => {m.body};") lines.append("") lines += [" }", "}", ""] return "\n".join(lines) + def out_param_body(self, method: Method) -> list[str]: + """The body of a method whose value MEOS writes through an out-parameter. + + MEOS answers `false` when the value does not exist and leaves the + out-parameter untouched, so the method answers null there and the value + otherwise.""" + name, size, reader = method.out_param + return [ + " {", + f" IntPtr _{name} = Marshal.AllocHGlobal({size});", + " try", + " {", + f" if (!{method.body})", + " {", + " return null;", + " }", + "", + f" return {reader};", + " }", + " finally", + " {", + f" Marshal.FreeHGlobal(_{name});", + " }", + " }", + ] + + def array_body(self, method: Method) -> list[str]: + """The body of a method taking a counted array. + + MEOS reads an array of its own values through a pointer to the first + element, so the wrappers' pointers are gathered into one array and pinned + for the call. MEOS copies what it keeps, so the pin lasts exactly as long + as the call does.""" + lines = [" {"] + for name, element in method.arrays: + lines += [ + f" IntPtr[] _{name}Values = new IntPtr[{ident(name)}.Length];", + f" for (int i = 0; i < {ident(name)}.Length; i++)", + " {", + f" _{name}Values[i] = {ident(name)}[i].Ptr;", + " }", + "", + f" GCHandle _{name} = GCHandle.Alloc(_{name}Values, GCHandleType.Pinned);", + ] + lines.append(" try") + lines.append(" {") + lines.append(f" return {method.body};") + lines.append(" }") + lines.append(" finally") + lines.append(" {") + for name, _ in method.arrays: + lines.append(f" _{name}.Free();") + lines += [" }", " }"] + return lines + def to_string(self, cls: str, methods: list) -> list[str]: """`ToString` over the class's own text output, where MEOS publishes one.