diff --git a/MEOS.NET.Tests/CallerAllocatedArrayTests.cs b/MEOS.NET.Tests/CallerAllocatedArrayTests.cs new file mode 100644 index 0000000..f1ea7a5 --- /dev/null +++ b/MEOS.NET.Tests/CallerAllocatedArrayTests.cs @@ -0,0 +1,39 @@ +using System.Runtime.InteropServices; + +using MEOS.NET.Functions; +using MEOS.NET.Types; + +namespace MEOS.NET.Tests +{ + /// + /// The `each` family fills an array the CALLER allocates, so the wrapper + /// takes that array rather than making one: MEOS writes one pointer per + /// member of the object, and storage for fewer of them is written past. + /// + [TestClass] + public class CallerAllocatedArrayTests : MeosTest + { + [TestMethod] + public void EachFillsTheArrayTheCallerGivesIt() + { + Jsonb jb = Jsonb.In("{\"a\": 1, \"b\": \"two\"}")!; + IntPtr values = Marshal.AllocHGlobal(IntPtr.Size * 8); + try + { + IntPtr[] keys = Meos.JsonbEach(jb.Ptr, values); + + Assert.AreEqual(2, keys.Length); + Assert.AreEqual("a", Meos.TextOut(keys[0])); + Assert.AreEqual("b", Meos.TextOut(keys[1])); + Assert.AreEqual("1", + Meos.JsonbOut(Marshal.ReadIntPtr(values, 0))); + Assert.AreEqual("\"two\"", + Meos.JsonbOut(Marshal.ReadIntPtr(values, IntPtr.Size))); + } + finally + { + Marshal.FreeHGlobal(values); + } + } + } +} diff --git a/MEOS.NET/Functions/Meos.meos_json.g.cs b/MEOS.NET/Functions/Meos.meos_json.g.cs index 27542e7..81fd440 100644 --- a/MEOS.NET/Functions/Meos.meos_json.g.cs +++ b/MEOS.NET/Functions/Meos.meos_json.g.cs @@ -105,52 +105,34 @@ public static IntPtr[] JsonArrayElementsText(IntPtr js) public static int JsonArrayLength(IntPtr js) => SafeExecution(() => Native.JsonArrayLength(js)); - public static (IntPtr[], IntPtr[]) JsonEach(IntPtr js) + public static IntPtr[] JsonEach(IntPtr js, IntPtr values) { - IntPtr _out_values = Marshal.AllocHGlobal(IntPtr.Size); - IntPtr _count_count = Marshal.AllocHGlobal(sizeof(int)); + IntPtr _cnt = Marshal.AllocHGlobal(sizeof(int)); try { - IntPtr _resultPtr = SafeExecution(() => Native.JsonEach(js, _out_values, _count_count)); - int _n = Marshal.ReadInt32(_count_count); - IntPtr[] _resultArr = new IntPtr[_n]; - for (int _i = 0; _i < _n; _i++) - { _resultArr[_i] = Marshal.ReadIntPtr(_resultPtr, _i * IntPtr.Size); } - IntPtr __out_values_arr = Marshal.ReadIntPtr(_out_values); - IntPtr[] __out_values_out = new IntPtr[_n]; + IntPtr _p = SafeExecution(() => Native.JsonEach(js, values, _cnt)); + int _n = Marshal.ReadInt32(_cnt); + IntPtr[] _out = new IntPtr[_n]; for (int _i = 0; _i < _n; _i++) - { __out_values_out[_i] = Marshal.ReadIntPtr(__out_values_arr, _i * IntPtr.Size); } - return (_resultArr, __out_values_out); - } - finally - { - Marshal.FreeHGlobal(_out_values); - Marshal.FreeHGlobal(_count_count); + { _out[_i] = Marshal.ReadIntPtr(_p, _i * IntPtr.Size); } + return _out; } + finally { Marshal.FreeHGlobal(_cnt); } } - public static (IntPtr[], IntPtr[]) JsonEachText(IntPtr js) + public static IntPtr[] JsonEachText(IntPtr js, IntPtr values) { - IntPtr _out_values = Marshal.AllocHGlobal(IntPtr.Size); - IntPtr _count_count = Marshal.AllocHGlobal(sizeof(int)); + IntPtr _cnt = Marshal.AllocHGlobal(sizeof(int)); try { - IntPtr _resultPtr = SafeExecution(() => Native.JsonEachText(js, _out_values, _count_count)); - int _n = Marshal.ReadInt32(_count_count); - IntPtr[] _resultArr = new IntPtr[_n]; - for (int _i = 0; _i < _n; _i++) - { _resultArr[_i] = Marshal.ReadIntPtr(_resultPtr, _i * IntPtr.Size); } - IntPtr __out_values_arr = Marshal.ReadIntPtr(_out_values); - IntPtr[] __out_values_out = new IntPtr[_n]; + IntPtr _p = SafeExecution(() => Native.JsonEachText(js, values, _cnt)); + int _n = Marshal.ReadInt32(_cnt); + IntPtr[] _out = new IntPtr[_n]; for (int _i = 0; _i < _n; _i++) - { __out_values_out[_i] = Marshal.ReadIntPtr(__out_values_arr, _i * IntPtr.Size); } - return (_resultArr, __out_values_out); - } - finally - { - Marshal.FreeHGlobal(_out_values); - Marshal.FreeHGlobal(_count_count); + { _out[_i] = Marshal.ReadIntPtr(_p, _i * IntPtr.Size); } + return _out; } + finally { Marshal.FreeHGlobal(_cnt); } } public static IntPtr JsonExtractPath(IntPtr js, IntPtr path_elems, int path_len) @@ -228,52 +210,34 @@ public static bool JsonbContained(IntPtr jb1, IntPtr jb2) public static bool JsonbContains(IntPtr jb1, IntPtr jb2) => SafeExecution(() => Native.JsonbContains(jb1, jb2)); - public static (IntPtr[], IntPtr[]) JsonbEach(IntPtr jb) + public static IntPtr[] JsonbEach(IntPtr jb, IntPtr values) { - IntPtr _out_values = Marshal.AllocHGlobal(IntPtr.Size); - IntPtr _count_count = Marshal.AllocHGlobal(sizeof(int)); + IntPtr _cnt = Marshal.AllocHGlobal(sizeof(int)); try { - IntPtr _resultPtr = SafeExecution(() => Native.JsonbEach(jb, _out_values, _count_count)); - int _n = Marshal.ReadInt32(_count_count); - IntPtr[] _resultArr = new IntPtr[_n]; - for (int _i = 0; _i < _n; _i++) - { _resultArr[_i] = Marshal.ReadIntPtr(_resultPtr, _i * IntPtr.Size); } - IntPtr __out_values_arr = Marshal.ReadIntPtr(_out_values); - IntPtr[] __out_values_out = new IntPtr[_n]; + IntPtr _p = SafeExecution(() => Native.JsonbEach(jb, values, _cnt)); + int _n = Marshal.ReadInt32(_cnt); + IntPtr[] _out = new IntPtr[_n]; for (int _i = 0; _i < _n; _i++) - { __out_values_out[_i] = Marshal.ReadIntPtr(__out_values_arr, _i * IntPtr.Size); } - return (_resultArr, __out_values_out); - } - finally - { - Marshal.FreeHGlobal(_out_values); - Marshal.FreeHGlobal(_count_count); + { _out[_i] = Marshal.ReadIntPtr(_p, _i * IntPtr.Size); } + return _out; } + finally { Marshal.FreeHGlobal(_cnt); } } - public static (IntPtr[], IntPtr[]) JsonbEachText(IntPtr jb) + public static IntPtr[] JsonbEachText(IntPtr jb, IntPtr values) { - IntPtr _out_values = Marshal.AllocHGlobal(IntPtr.Size); - IntPtr _count_count = Marshal.AllocHGlobal(sizeof(int)); + IntPtr _cnt = Marshal.AllocHGlobal(sizeof(int)); try { - IntPtr _resultPtr = SafeExecution(() => Native.JsonbEachText(jb, _out_values, _count_count)); - int _n = Marshal.ReadInt32(_count_count); - IntPtr[] _resultArr = new IntPtr[_n]; - for (int _i = 0; _i < _n; _i++) - { _resultArr[_i] = Marshal.ReadIntPtr(_resultPtr, _i * IntPtr.Size); } - IntPtr __out_values_arr = Marshal.ReadIntPtr(_out_values); - IntPtr[] __out_values_out = new IntPtr[_n]; + IntPtr _p = SafeExecution(() => Native.JsonbEachText(jb, values, _cnt)); + int _n = Marshal.ReadInt32(_cnt); + IntPtr[] _out = new IntPtr[_n]; for (int _i = 0; _i < _n; _i++) - { __out_values_out[_i] = Marshal.ReadIntPtr(__out_values_arr, _i * IntPtr.Size); } - return (_resultArr, __out_values_out); - } - finally - { - Marshal.FreeHGlobal(_out_values); - Marshal.FreeHGlobal(_count_count); + { _out[_i] = Marshal.ReadIntPtr(_p, _i * IntPtr.Size); } + return _out; } + finally { Marshal.FreeHGlobal(_cnt); } } public static bool JsonbExists(IntPtr jb, IntPtr key) diff --git a/MEOS.NET/Functions/Meos.pgtypes.g.cs b/MEOS.NET/Functions/Meos.pgtypes.g.cs index 5dd3553..5992523 100644 --- a/MEOS.NET/Functions/Meos.pgtypes.g.cs +++ b/MEOS.NET/Functions/Meos.pgtypes.g.cs @@ -534,52 +534,34 @@ public static IntPtr[] PgJsonArrayElementsText(IntPtr js) public static int PgJsonArrayLength(IntPtr js) => SafeExecution(() => Native.PgJsonArrayLength(js)); - public static (IntPtr[], IntPtr[]) PgJsonEach(IntPtr js) + public static IntPtr[] PgJsonEach(IntPtr js, IntPtr values) { - IntPtr _out_values = Marshal.AllocHGlobal(IntPtr.Size); - IntPtr _count_count = Marshal.AllocHGlobal(sizeof(int)); + IntPtr _cnt = Marshal.AllocHGlobal(sizeof(int)); try { - IntPtr _resultPtr = SafeExecution(() => Native.PgJsonEach(js, _out_values, _count_count)); - int _n = Marshal.ReadInt32(_count_count); - IntPtr[] _resultArr = new IntPtr[_n]; - for (int _i = 0; _i < _n; _i++) - { _resultArr[_i] = Marshal.ReadIntPtr(_resultPtr, _i * IntPtr.Size); } - IntPtr __out_values_arr = Marshal.ReadIntPtr(_out_values); - IntPtr[] __out_values_out = new IntPtr[_n]; + IntPtr _p = SafeExecution(() => Native.PgJsonEach(js, values, _cnt)); + int _n = Marshal.ReadInt32(_cnt); + IntPtr[] _out = new IntPtr[_n]; for (int _i = 0; _i < _n; _i++) - { __out_values_out[_i] = Marshal.ReadIntPtr(__out_values_arr, _i * IntPtr.Size); } - return (_resultArr, __out_values_out); - } - finally - { - Marshal.FreeHGlobal(_out_values); - Marshal.FreeHGlobal(_count_count); + { _out[_i] = Marshal.ReadIntPtr(_p, _i * IntPtr.Size); } + return _out; } + finally { Marshal.FreeHGlobal(_cnt); } } - public static (IntPtr[], IntPtr[]) PgJsonEachText(IntPtr js) + public static IntPtr[] PgJsonEachText(IntPtr js, IntPtr values) { - IntPtr _out_values = Marshal.AllocHGlobal(IntPtr.Size); - IntPtr _count_count = Marshal.AllocHGlobal(sizeof(int)); + IntPtr _cnt = Marshal.AllocHGlobal(sizeof(int)); try { - IntPtr _resultPtr = SafeExecution(() => Native.PgJsonEachText(js, _out_values, _count_count)); - int _n = Marshal.ReadInt32(_count_count); - IntPtr[] _resultArr = new IntPtr[_n]; - for (int _i = 0; _i < _n; _i++) - { _resultArr[_i] = Marshal.ReadIntPtr(_resultPtr, _i * IntPtr.Size); } - IntPtr __out_values_arr = Marshal.ReadIntPtr(_out_values); - IntPtr[] __out_values_out = new IntPtr[_n]; + IntPtr _p = SafeExecution(() => Native.PgJsonEachText(js, values, _cnt)); + int _n = Marshal.ReadInt32(_cnt); + IntPtr[] _out = new IntPtr[_n]; for (int _i = 0; _i < _n; _i++) - { __out_values_out[_i] = Marshal.ReadIntPtr(__out_values_arr, _i * IntPtr.Size); } - return (_resultArr, __out_values_out); - } - finally - { - Marshal.FreeHGlobal(_out_values); - Marshal.FreeHGlobal(_count_count); + { _out[_i] = Marshal.ReadIntPtr(_p, _i * IntPtr.Size); } + return _out; } + finally { Marshal.FreeHGlobal(_cnt); } } public static IntPtr[] PgJsonObjectKeys(IntPtr js) @@ -642,52 +624,34 @@ public static bool PgJsonbContained(IntPtr jb1, IntPtr jb2) public static bool PgJsonbContains(IntPtr jb1, IntPtr jb2) => SafeExecution(() => Native.PgJsonbContains(jb1, jb2)); - public static (IntPtr[], IntPtr[]) PgJsonbEach(IntPtr jb) + public static IntPtr[] PgJsonbEach(IntPtr jb, IntPtr values) { - IntPtr _out_values = Marshal.AllocHGlobal(IntPtr.Size); - IntPtr _count_count = Marshal.AllocHGlobal(sizeof(int)); + IntPtr _cnt = Marshal.AllocHGlobal(sizeof(int)); try { - IntPtr _resultPtr = SafeExecution(() => Native.PgJsonbEach(jb, _out_values, _count_count)); - int _n = Marshal.ReadInt32(_count_count); - IntPtr[] _resultArr = new IntPtr[_n]; - for (int _i = 0; _i < _n; _i++) - { _resultArr[_i] = Marshal.ReadIntPtr(_resultPtr, _i * IntPtr.Size); } - IntPtr __out_values_arr = Marshal.ReadIntPtr(_out_values); - IntPtr[] __out_values_out = new IntPtr[_n]; + IntPtr _p = SafeExecution(() => Native.PgJsonbEach(jb, values, _cnt)); + int _n = Marshal.ReadInt32(_cnt); + IntPtr[] _out = new IntPtr[_n]; for (int _i = 0; _i < _n; _i++) - { __out_values_out[_i] = Marshal.ReadIntPtr(__out_values_arr, _i * IntPtr.Size); } - return (_resultArr, __out_values_out); - } - finally - { - Marshal.FreeHGlobal(_out_values); - Marshal.FreeHGlobal(_count_count); + { _out[_i] = Marshal.ReadIntPtr(_p, _i * IntPtr.Size); } + return _out; } + finally { Marshal.FreeHGlobal(_cnt); } } - public static (IntPtr[], IntPtr[]) PgJsonbEachText(IntPtr jb) + public static IntPtr[] PgJsonbEachText(IntPtr jb, IntPtr values) { - IntPtr _out_values = Marshal.AllocHGlobal(IntPtr.Size); - IntPtr _count_count = Marshal.AllocHGlobal(sizeof(int)); + IntPtr _cnt = Marshal.AllocHGlobal(sizeof(int)); try { - IntPtr _resultPtr = SafeExecution(() => Native.PgJsonbEachText(jb, _out_values, _count_count)); - int _n = Marshal.ReadInt32(_count_count); - IntPtr[] _resultArr = new IntPtr[_n]; - for (int _i = 0; _i < _n; _i++) - { _resultArr[_i] = Marshal.ReadIntPtr(_resultPtr, _i * IntPtr.Size); } - IntPtr __out_values_arr = Marshal.ReadIntPtr(_out_values); - IntPtr[] __out_values_out = new IntPtr[_n]; + IntPtr _p = SafeExecution(() => Native.PgJsonbEachText(jb, values, _cnt)); + int _n = Marshal.ReadInt32(_cnt); + IntPtr[] _out = new IntPtr[_n]; for (int _i = 0; _i < _n; _i++) - { __out_values_out[_i] = Marshal.ReadIntPtr(__out_values_arr, _i * IntPtr.Size); } - return (_resultArr, __out_values_out); - } - finally - { - Marshal.FreeHGlobal(_out_values); - Marshal.FreeHGlobal(_count_count); + { _out[_i] = Marshal.ReadIntPtr(_p, _i * IntPtr.Size); } + return _out; } + finally { Marshal.FreeHGlobal(_cnt); } } public static bool PgJsonbEq(IntPtr jb1, IntPtr jb2) diff --git a/MEOS.NET/Types/Jsonb.g.cs b/MEOS.NET/Types/Jsonb.g.cs index d08e44c..210a745 100644 --- a/MEOS.NET/Types/Jsonb.g.cs +++ b/MEOS.NET/Types/Jsonb.g.cs @@ -86,20 +86,6 @@ public bool Contained(Jsonb jb2) } } - public (Text?[], Jsonb?[]) Each() - { - var _answered = Meos.JsonbEach(this.Ptr); - - return (MEOSFactory.WrapTextArray(_answered.Item1), MEOSFactory.WrapJsonbArray(_answered.Item2)); - } - - public (Text?[], Text?[]) EachText() - { - var _answered = Meos.JsonbEachText(this.Ptr); - - return (MEOSFactory.WrapTextArray(_answered.Item1), MEOSFactory.WrapTextArray(_answered.Item2)); - } - public bool Exists(Text key) => Meos.JsonbExists(this.Ptr, key.Ptr);