Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions MEOS.NET.Tests/CatalogValueTypeTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using MEOS.NET.Enums;
using MEOS.NET.Structures;
using MEOS.NET.Types;

namespace MEOS.NET.Tests
{
/// <summary>
/// Whatever the wrapper already states as a C# value — an enum the catalog
/// names, a scalar behind a MEOS typedef, a struct carried by value — the
/// object layer hands on as that value.
/// </summary>
[TestClass]
public class CatalogValueTypeTests : MeosTest
{
[TestMethod]
public void AnEnumArgumentIsTheEnumTheCatalogNames()
{
TJsonb temp = (TJsonb)TJsonb.In(
"[{\"a\": [1, 2]}@2024-12-06, {\"a\": [1, 2]}@2024-12-08]")!;

Temporal? first = temp.ArrayElement(0, true, NullHandleType.NullJsonNull);

Assert.IsNotNull(first);
}

[TestMethod]
public void AScalarBehindATypedefComesBackAsThatScalar()
{
Geo point = Geo.FromText("POINT(1 1)", 4326)!;

ulong cell = point.ToS2cellCell(10);

Assert.AreNotEqual(0UL, cell);
}

[TestMethod]
public void AStructReturnedByValueComesBackAsTheStruct()
{
TPoint trip = (TPoint)TGeomPoint.In(
"[POINT(0 0)@2024-12-06, POINT(2 2)@2024-12-08]")!;
STBox bounds = STBox.In("STBOX X((-1,-1),(3,3))")!;

MvtGeom mvt = trip.AsMvtgeom(bounds, 4096, 0, true);

Assert.AreNotEqual(IntPtr.Zero, mvt.geom);
Assert.IsTrue(mvt.count > 0);
}
}
}
18 changes: 18 additions & 0 deletions MEOS.NET/Functions/Meos.Native.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9213,6 +9213,24 @@ private static partial class Native
[LibraryImport(DllPath, EntryPoint = "geo_edge_ctx_make", StringMarshalling = StringMarshalling.Utf8)]
internal static partial IntPtr GeoEdgeCtxMake(IntPtr gs);

[LibraryImport(DllPath, EntryPoint = "geo_is_planar_linear", StringMarshalling = StringMarshalling.Utf8)]
[return: MarshalAs(UnmanagedType.U1)]
internal static partial bool GeoIsPlanarLinear(IntPtr gs);

[LibraryImport(DllPath, EntryPoint = "geo_is_point_set", StringMarshalling = StringMarshalling.Utf8)]
[return: MarshalAs(UnmanagedType.U1)]
internal static partial bool GeoIsPointSet(IntPtr gs);

[LibraryImport(DllPath, EntryPoint = "geo_meos_supported", StringMarshalling = StringMarshalling.Utf8)]
[return: MarshalAs(UnmanagedType.U1)]
internal static partial bool GeoMeosSupported(IntPtr gs);

[LibraryImport(DllPath, EntryPoint = "geo_points_covered", StringMarshalling = StringMarshalling.Utf8)]
internal static partial IntPtr GeoPointsCovered(IntPtr pts, IntPtr gs, [MarshalAs(UnmanagedType.U1)] bool covered);

[LibraryImport(DllPath, EntryPoint = "geo_clip_linear_geom", StringMarshalling = StringMarshalling.Utf8)]
internal static partial IntPtr GeoClipLinearGeom(IntPtr line, IntPtr gs, [MarshalAs(UnmanagedType.U1)] bool inside);

[LibraryImport(DllPath, EntryPoint = "geo_edge_ctx_free", StringMarshalling = StringMarshalling.Utf8)]
internal static partial void GeoEdgeCtxFree(IntPtr ctx);

Expand Down
15 changes: 15 additions & 0 deletions MEOS.NET/Functions/Meos.meos_internal_geo.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,21 @@ public static IntPtr TgeoseqsetRestrictStbox(IntPtr ss, IntPtr box, bool border_
public static IntPtr GeoEdgeCtxMake(IntPtr gs)
=> SafeExecution<IntPtr>(() => Native.GeoEdgeCtxMake(gs));

public static bool GeoIsPlanarLinear(IntPtr gs)
=> SafeExecution<bool>(() => Native.GeoIsPlanarLinear(gs));

public static bool GeoIsPointSet(IntPtr gs)
=> SafeExecution<bool>(() => Native.GeoIsPointSet(gs));

public static bool GeoMeosSupported(IntPtr gs)
=> SafeExecution<bool>(() => Native.GeoMeosSupported(gs));

public static IntPtr GeoPointsCovered(IntPtr pts, IntPtr gs, bool covered)
=> SafeExecution<IntPtr>(() => Native.GeoPointsCovered(pts, gs, covered));

public static IntPtr GeoClipLinearGeom(IntPtr line, IntPtr gs, bool inside)
=> SafeExecution<IntPtr>(() => Native.GeoClipLinearGeom(line, gs, inside));

public static void GeoEdgeCtxFree(IntPtr ctx)
=> SafeExecution(() => Native.GeoEdgeCtxFree(ctx));

Expand Down
3 changes: 3 additions & 0 deletions MEOS.NET/Types/Geo.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ public ulong ToH3indexCell(int resolution)
public ulong ToQuadbinCell(int resolution)
=> Meos.GeoToQuadbinCell(this.Ptr, resolution);

public ulong ToS2cellCell(int level)
=> Meos.GeoToS2cellCell(this.Ptr, level);

public Set? ToSet()
=> MEOSFactory.WrapSet(Meos.GeoToSet(this.Ptr));

Expand Down
6 changes: 6 additions & 0 deletions MEOS.NET/Types/Jsonb.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,12 @@ public bool ToBool()
public string ToCstring()
=> Meos.JsonbToCstring(this.Ptr);

public float ToFloat4()
=> Meos.JsonbToFloat4(this.Ptr);

public double ToFloat8()
=> Meos.JsonbToFloat8(this.Ptr);

public short ToInt16()
=> Meos.JsonbToInt16(this.Ptr);

Expand Down
19 changes: 19 additions & 0 deletions MEOS.NET/Types/Raquet.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,25 @@ public int Width()
public static Raquet? In(string str)
=> MEOSFactory.WrapRaquet(Meos.RaquetIn(str));

public static Raquet? Make(ulong quadbin, int width, int height, MeosPixType pixtype, double nodata, bool has_nodata, byte[] pixels)
{
GCHandle _pixels = GCHandle.Alloc(pixels, GCHandleType.Pinned);
try
{
return MEOSFactory.WrapRaquet(Meos.RaquetMake(quadbin, width, height, (int) pixtype, nodata, has_nodata, _pixels.AddrOfPinnedObject(), (ulong) pixels.Length));
}
finally
{
_pixels.Free();
}
}

public static MeosPixType PixtypeFromString(string str)
=> (MeosPixType) Meos.RaquetPixtypeFromString(str);

public static ulong PixtypeSize(MeosPixType pixtype)
=> Meos.RaquetPixtypeSize((int) pixtype);

public static Raquet? Read(string path, ulong quadbin)
=> MEOSFactory.WrapRaquet(Meos.RaquetRead(path, quadbin));

Expand Down
17 changes: 17 additions & 0 deletions MEOS.NET/Types/TGeo.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ internal TGeo(IntPtr ptr) : base(ptr) { }
public STBox?[] SpaceBoxes(double xsize, double ysize, double zsize, Geo sorigin, bool bitmatrix, bool border_inc)
=> MEOSFactory.WrapSTBoxArray(Meos.TgeoSpaceBoxes(this.Ptr, xsize, ysize, zsize, sorigin.Ptr, bitmatrix, border_inc));

public SpaceSplit SpaceSplit(double xsize, double ysize, double zsize, Geo sorigin, bool bitmatrix, bool border_inc)
=> Meos.TgeoSpaceSplit(this.Ptr, xsize, ysize, zsize, sorigin.Ptr, bitmatrix, border_inc);

public STBox?[] SpaceTimeBoxes(double xsize, double ysize, double zsize, Interval duration, Geo sorigin, DateTime torigin, bool bitmatrix, bool border_inc)
{
IntPtr _duration = Marshal.AllocHGlobal(Marshal.SizeOf<Interval>());
Expand All @@ -75,6 +78,20 @@ internal TGeo(IntPtr ptr) : base(ptr) { }
}
}

public SpaceTimeSplit SpaceTimeSplit(double xsize, double ysize, double zsize, Interval duration, Geo sorigin, DateTime torigin, bool bitmatrix, bool border_inc)
{
IntPtr _duration = Marshal.AllocHGlobal(Marshal.SizeOf<Interval>());
try
{
Marshal.StructureToPtr(duration, _duration, false);
return Meos.TgeoSpaceTimeSplit(this.Ptr, xsize, ysize, zsize, _duration, sorigin.Ptr, MEOSConvert.ToTimestampTz(torigin), bitmatrix, border_inc);
}
finally
{
Marshal.FreeHGlobal(_duration);
}
}

public STBox?[] SplitEachNStboxes(int elem_count)
=> MEOSFactory.WrapSTBoxArray(Meos.TgeoSplitEachNStboxes(this.Ptr, elem_count));

Expand Down
37 changes: 37 additions & 0 deletions MEOS.NET/Types/TJsonb.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ internal TJsonb(IntPtr ptr) : base(ptr) { }
public override string ToString()
=> this.Out();

public Temporal? ArrayElement(int idx, bool astext, NullHandleType null_handle)
=> MEOSFactory.WrapTemporal(Meos.TjsonbArrayElement(this.Ptr, idx, astext, (int) null_handle));

public Temporal? ArrayLength()
=> MEOSFactory.WrapTemporal(Meos.TjsonbArrayLength(this.Ptr));

Expand Down Expand Up @@ -131,6 +134,25 @@ public override string ToString()
}
}

public Temporal? ExtractPath(Text[] path_elems, bool astext, NullHandleType null_handle)
{
IntPtr[] _path_elemsValues = new IntPtr[path_elems.Length];
for (int i = 0; i < path_elems.Length; i++)
{
_path_elemsValues[i] = path_elems[i].Ptr;
}

GCHandle _path_elems = GCHandle.Alloc(_path_elemsValues, GCHandleType.Pinned);
try
{
return MEOSFactory.WrapTemporal(Meos.TjsonbExtractPath(this.Ptr, _path_elems.AddrOfPinnedObject(), path_elems.Length, astext, (int) null_handle));
}
finally
{
_path_elems.Free();
}
}

public Temporal? Insert(Text[] keys, Jsonb newjb, bool after)
{
IntPtr[] _keysValues = new IntPtr[keys.Length];
Expand All @@ -153,6 +175,9 @@ public override string ToString()
public Temporal? MinusValue(Jsonb jsb)
=> MEOSFactory.WrapTemporal(Meos.TjsonbMinusValue(this.Ptr, jsb.Ptr));

public Temporal? ObjectField(Text key, bool astext, NullHandleType null_handle)
=> MEOSFactory.WrapTemporal(Meos.TjsonbObjectField(this.Ptr, key.Ptr, astext, (int) null_handle));

public string Out()
=> Meos.TjsonbOut(this.Ptr);

Expand Down Expand Up @@ -184,9 +209,21 @@ public string Out()
public Temporal? StripNulls(bool strip_in_arrays)
=> MEOSFactory.WrapTemporal(Meos.TjsonbStripNulls(this.Ptr, strip_in_arrays));

public Temporal? ToTbool(string key, NullHandleType null_handle)
=> MEOSFactory.WrapTemporal(Meos.TjsonbToTbool(this.Ptr, key, (int) null_handle));

public Temporal? ToTfloat(string key, InterpType interp, NullHandleType null_handle)
=> MEOSFactory.WrapTemporal(Meos.TjsonbToTfloat(this.Ptr, key, (int) interp, (int) null_handle));

public Temporal? ToTint(string key, NullHandleType null_handle)
=> MEOSFactory.WrapTemporal(Meos.TjsonbToTint(this.Ptr, key, (int) null_handle));

public Temporal? ToTtext()
=> MEOSFactory.WrapTemporal(Meos.TjsonbToTtext(this.Ptr));

public Temporal? ToTtextKey(string key, NullHandleType null_handle)
=> MEOSFactory.WrapTemporal(Meos.TjsonbToTtextKey(this.Ptr, key, (int) null_handle));

public Jsonb? ValueAtTimestamptz(DateTime t, bool strict)
{
IntPtr _value = Marshal.AllocHGlobal(8);
Expand Down
3 changes: 3 additions & 0 deletions MEOS.NET/Types/TPoint.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ internal TPoint(IntPtr ptr) : base(ptr) { }
public Temporal? AngularDifference()
=> MEOSFactory.WrapTemporal(Meos.TpointAngularDifference(this.Ptr));

public MvtGeom AsMvtgeom(STBox bounds, int extent, int buffer, bool clip_geom)
=> Meos.TpointAsMvtgeom(this.Ptr, bounds.Ptr, extent, buffer, clip_geom);

public Temporal? AtElevation(Span s)
=> MEOSFactory.WrapTemporal(Meos.TpointAtElevation(this.Ptr, s.Ptr));

Expand Down
6 changes: 6 additions & 0 deletions MEOS.NET/Types/Text.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ internal Text(IntPtr ptr) : base(ptr) { }
public override string ToString()
=> this.Out();

public uint Hash(uint collid)
=> Meos.TextHash(this.Ptr, collid);

public ulong HashExtended(ulong seed, uint collid)
=> Meos.TextHashExtended(this.Ptr, seed, collid);

public Text? Initcap()
=> MEOSFactory.WrapText(Meos.TextInitcap(this.Ptr));

Expand Down
34 changes: 22 additions & 12 deletions tools/objectgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,18 @@
"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 = {
"bool", "char", "int", "int8", "int8_t", "uint8", "uint8_t", "int16", "int16_t",
"uint16", "uint16_t", "int32", "int32_t", "uint32", "uint32_t", "int64",
"int64_t", "uint64", "uint64_t", "long", "double", "float", "size_t",
"char *", "void",
}
def is_scalar(cs_type: str) -> bool:
"""Whether the wrapper already states this as a C# value the layer hands on.

The wrapper's own C# type is what decides it: codegen resolves every scalar
the catalog names — through the typedefs it carries, so `S2CellId` reads
`ulong` and `float8` reads `double` — and a struct it carries by value is a
value too. A second list of C spellings here would answer for the ones the
layer was told about and defer the rest."""
return cs_type in _SCALAR_CS or cs_type in codegen.BY_VALUE_STRUCTS


_SCALAR_CS = set(codegen.SCALAR_MAP.values()) | {"void", "bool", "string", "string?"}

# Acronym runs the error names carry, kept upper-case so the C# spelling reads
# the way the catalog's own camelCase names do (`asMFJSON`).
Expand Down Expand Up @@ -308,7 +312,9 @@ def map_return(self, f: dict, wrapper_ret: str) -> tuple[str, str] | None:
return ("DateOnly", "MEOSConvert.ToDateOnly($)")
if wrapper_ret in ("string", "string?"):
return (wrapper_ret, "$")
if c in PASSTHROUGH_C and wrapper_ret != "IntPtr":
if c in codegen.ENUM_TYPES:
return (enum_type_name(c), f"({enum_type_name(c)}) $")
if is_scalar(wrapper_ret):
return (wrapper_ret, "$")
cls = self.m.class_for_ctype(c)
if cls and wrapper_ret == "IntPtr":
Expand Down Expand Up @@ -361,9 +367,13 @@ def map_param(self, c_type: str, cs_type: str, name: str) -> tuple[str, str] | N
return ("DateTime", f"MEOSConvert.ToTimestampTz({name})")
if c == "DateADT":
return ("DateOnly", f"MEOSConvert.ToDateADT({name})")
if c == "interpType":
return ("InterpType", f"(int) {name}")
if c in PASSTHROUGH_C and cs_type != "IntPtr":
if c in codegen.ENUM_TYPES:
# The wrapper takes the enum's value as an int, and the catalog
# already names every enum the surface uses — so a method takes the
# C# enum whichever one it is, rather than the one enum the layer
# was told about.
return (enum_type_name(c), f"(int) {name}")
if is_scalar(cs_type):
return (cs_type, name)
if cs_type == "string":
return ("string", name)
Expand Down
Loading