From 9947655df16d216816761c234800fea5c38cfef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20Zim=C3=A1nyi?= Date: Thu, 3 Sep 2026 17:58:19 +0200 Subject: [PATCH] Answer the extended WKB of a geometry as the buffer it is MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The catalog states `size` as the parameter MEOS writes the length of `geo_as_ewkb`'s buffer into, so the method reads it: `AsEWKB(string endian)` answers a `byte[]` exactly as long as the data, joining the twenty-eight other buffers the layer already folds that way. The length is the whole of it — an extended WKB buffer carries no terminator and no length of its own, so a caller holding the pointer without it has no way to say where the geometry ends. The layer emits 1353 methods over 115 classes with 7 deferred. Its own test reads the hex form of the same geometry as an independent statement of the same length: `AsHexewkb` answers a string of exactly twice as many characters, and hex-encoding the buffer reproduces it character for character, so a buffer of the wrong length fails on the count before it fails on the content. The second test round-trips the bytes back through `FromEWKB` to the value they came from. --- MEOS.NET.Tests/ExtendedWkbTests.cs | 39 ++++++++++++++++++++++++++++++ MEOS.NET/Types/Geo.g.cs | 21 ++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 MEOS.NET.Tests/ExtendedWkbTests.cs diff --git a/MEOS.NET.Tests/ExtendedWkbTests.cs b/MEOS.NET.Tests/ExtendedWkbTests.cs new file mode 100644 index 0000000..8ad4b43 --- /dev/null +++ b/MEOS.NET.Tests/ExtendedWkbTests.cs @@ -0,0 +1,39 @@ +using MEOS.NET.Types; + +namespace MEOS.NET.Tests +{ + /// + /// The extended WKB of a geometry is a buffer whose length MEOS states + /// through a pointer, so the array a caller gets is exactly as long as the + /// data — which the hex form of the same value states independently. + /// + [TestClass] + public class ExtendedWkbTests : MeosTest + { + private const string Line = "SRID=4326;LINESTRING(1 1, 2 2, 3 4)"; + + [TestMethod] + public void TheBufferIsAsLongAsTheHexFormSays() + { + Geo line = Geometry.In(Line, -1)!; + + byte[]? ewkb = line.AsEWKB("ndr"); + string hex = line.AsHexewkb("ndr"); + + Assert.IsNotNull(ewkb); + Assert.AreEqual(hex.Length, ewkb!.Length * 2); + Assert.AreEqual(hex.ToUpperInvariant(), Convert.ToHexString(ewkb)); + } + + [TestMethod] + public void AGeometryRoundTripsThroughItsOwnEWKB() + { + Geo line = Geometry.In(Line, -1)!; + + Geo? read = Geo.FromEWKB(line.AsEWKB("ndr")!, 4326); + + Assert.IsNotNull(read); + Assert.AreEqual(line.ToString(), read!.ToString()); + } + } +} diff --git a/MEOS.NET/Types/Geo.g.cs b/MEOS.NET/Types/Geo.g.cs index 266d0e7..0b31382 100644 --- a/MEOS.NET/Types/Geo.g.cs +++ b/MEOS.NET/Types/Geo.g.cs @@ -18,6 +18,27 @@ internal Geo(IntPtr ptr) : base(ptr) { } public override string ToString() => this.Out(); + public byte[]? AsEWKB(string endian) + { + IntPtr _size = Marshal.AllocHGlobal(sizeof(long)); + try + { + IntPtr _bytes = Meos.GeoAsEwkb(this.Ptr, endian, _size); + if (_bytes == IntPtr.Zero) + { + return null; + } + + byte[] _wkb = new byte[Marshal.ReadInt64(_size)]; + Marshal.Copy(_bytes, _wkb, 0, _wkb.Length); + return _wkb; + } + finally + { + Marshal.FreeHGlobal(_size); + } + } + public string AsEWKT(int precision) => Meos.GeoAsEwkt(this.Ptr, precision);