From c8e5fa0c16f350a8cf8d2019cbd5912f7d74ac7c Mon Sep 17 00:00:00 2001 From: Peter Stace Date: Fri, 19 Nov 2021 06:31:17 +1100 Subject: [PATCH] Use a stub implementation of MakeValid when not supported by GEOS --- geos/entrypoints.go | 15 +++++++++++++++ geos/entrypoints_test.go | 3 +++ geos/errors.go | 20 ++++++++++++++++++++ geos/handle.go | 2 +- 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/geos/entrypoints.go b/geos/entrypoints.go index 76238ff3..a6a8fb3b 100644 --- a/geos/entrypoints.go +++ b/geos/entrypoints.go @@ -4,6 +4,17 @@ package geos #cgo LDFLAGS: -lgeos_c #cgo CFLAGS: -Wall #include "geos_c.h" + +#define MAKE_VALID_MIN_VERSION "3.8.0" +#define MAKE_VALID_MISSING ( \ + GEOS_VERSION_MAJOR < 3 || \ + (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR < 8) \ +) +#if MAKE_VALID_MISSING +// This stub implementation also fails +GEOSGeometry *GEOSMakeValid_r(GEOSContextHandle_t handle, const GEOSGeometry* g) { return NULL; } +#endif + */ import "C" @@ -316,6 +327,10 @@ func SymmetricDifference(a, b geom.Geometry, opts ...geom.ConstructorOption) (ge // invalid geometry. If the input geometry is valid, then it is returned // unaltered. func MakeValid(g geom.Geometry, opts ...geom.ConstructorOption) (geom.Geometry, error) { + if C.MAKE_VALID_MISSING != 0 { + return geom.Geometry{}, unsupportedGEOSVersionError{ + C.MAKE_VALID_MIN_VERSION, "MakeValid"} + } result, err := unaryOpG(g, opts, func(ctx C.GEOSContextHandle_t, g *C.GEOSGeometry) *C.GEOSGeometry { return C.GEOSMakeValid_r(ctx, g) }) diff --git a/geos/entrypoints_test.go b/geos/entrypoints_test.go index 43ec1a66..fef8096c 100644 --- a/geos/entrypoints_test.go +++ b/geos/entrypoints_test.go @@ -781,6 +781,9 @@ func TestMakeValid(t *testing.T) { t.Run(strconv.Itoa(i), func(t *testing.T) { in := geomFromWKT(t, tt.input, geom.DisableAllValidations) gotGeom, err := MakeValid(in) + if _, ok := err.(unsupportedGEOSVersionError); ok { + t.Skip(err) + } expectNoErr(t, err) wantGeom := geomFromWKT(t, tt.wantOutput) expectGeomEq(t, gotGeom, wantGeom) diff --git a/geos/errors.go b/geos/errors.go index ea29198d..a0cd66ad 100644 --- a/geos/errors.go +++ b/geos/errors.go @@ -2,9 +2,29 @@ package geos import "fmt" +// #include "geos_c.h" +import "C" + func wrap(err error, format string, args ...interface{}) error { if err == nil { return nil } return fmt.Errorf(format+": %w", append(args, err)...) } + +var currentGEOSVersion = fmt.Sprintf( + "%d.%d.%d", + C.GEOS_VERSION_MAJOR, + C.GEOS_VERSION_MINOR, + C.GEOS_VERSION_PATCH, +) + +type unsupportedGEOSVersionError struct { + requiredGEOSVersion string + operation string +} + +func (e unsupportedGEOSVersionError) Error() string { + return fmt.Sprintf("%s is unsupported in GEOS %s, requires at least GEOS %s", + e.operation, currentGEOSVersion, e.requiredGEOSVersion) +} diff --git a/geos/handle.go b/geos/handle.go index 93845d75..c7eacc1d 100644 --- a/geos/handle.go +++ b/geos/handle.go @@ -22,7 +22,6 @@ char *marshal(GEOSContextHandle_t handle, const GEOSGeometry *g, size_t *size, c GEOSGeometry const *noop(GEOSContextHandle_t handle, const GEOSGeometry *g) { return g; } - */ import "C" @@ -62,6 +61,7 @@ func newHandle() (*handle, error) { h.release() return nil, errors.New("malloc failed") } + C.memset((unsafe.Pointer)(h.errBuf), 0, 1024) h.context = C.sf_init(unsafe.Pointer(h.errBuf)) if h.context == nil {