19 #if defined(ENABLE_GEOS) && !defined(_WIN32)
27 #ifndef GEOS_LIBRARY_FILENAME
28 #error Configuration should include GEOS library file name
32 std::unique_ptr<std::string> g_libgeos_so_filename(
33 new std::string(GEOS_LIBRARY_FILENAME));
35 namespace Geospatial {
37 using PFN_GEOS_init_r = GEOSContextHandle_t (*)();
38 using PFN_GEOS_finish_r = void (*)(GEOSContextHandle_t);
39 using PFN_GEOSisValidDetail_r =
40 char (*)(GEOSContextHandle_t,
const GEOSGeometry*, int,
char**, GEOSGeometry**);
41 using PFN_GEOSGeomFromWKB_buf_r = GEOSGeometry* (*)(GEOSContextHandle_t,
44 using PFN_GEOSGeom_destroy_r = void (*)(GEOSContextHandle_t, GEOSGeometry*);
45 using PFN_GEOSFree_r = void (*)(GEOSContextHandle_t,
void*);
47 static bool geos_can_validate =
true;
48 static void* geos_dso_handle =
nullptr;
50 static std::mutex geos_dso_mutex;
52 static PFN_GEOS_init_r pfn_GEOS_init_r =
nullptr;
53 static PFN_GEOS_finish_r pfn_GEOS_finish_r =
nullptr;
54 static PFN_GEOSisValidDetail_r pfn_GEOSisValidDetail_r =
nullptr;
55 static PFN_GEOSGeomFromWKB_buf_r pfn_GEOSGeomFromWKB_buf_r =
nullptr;
56 static PFN_GEOSGeom_destroy_r pfn_GEOSGeom_destroy_r =
nullptr;
57 static PFN_GEOSFree_r pfn_GEOSFree_r =
nullptr;
61 std::lock_guard<std::mutex> guard(geos_dso_mutex);
64 if (!geos_can_validate) {
69 if (geos_dso_handle) {
74 if (!g_libgeos_so_filename) {
76 <<
"GEOS dynamic library filename unspecified. Geometry validation unavailable.";
77 geos_can_validate =
false;
82 auto const* geos_dso_filename = g_libgeos_so_filename->c_str();
83 geos_dso_handle = dlopen(geos_dso_filename, RTLD_NOW | RTLD_LOCAL);
84 if (!geos_dso_handle) {
85 LOG(
WARNING) <<
"Failed to dynamically load GEOS. Geometry validation unavailable.";
86 geos_can_validate =
false;
91 pfn_GEOS_init_r = (PFN_GEOS_init_r)dlsym(geos_dso_handle,
"GEOS_init_r");
92 pfn_GEOS_finish_r = (PFN_GEOS_finish_r)dlsym(geos_dso_handle,
"GEOS_finish_r");
93 pfn_GEOSisValidDetail_r =
94 (PFN_GEOSisValidDetail_r)dlsym(geos_dso_handle,
"GEOSisValidDetail_r");
95 pfn_GEOSGeomFromWKB_buf_r =
96 (PFN_GEOSGeomFromWKB_buf_r)dlsym(geos_dso_handle,
"GEOSGeomFromWKB_buf_r");
97 pfn_GEOSGeom_destroy_r =
98 (PFN_GEOSGeom_destroy_r)dlsym(geos_dso_handle,
"GEOSGeom_destroy_r");
99 pfn_GEOSFree_r = (PFN_GEOSFree_r)dlsym(geos_dso_handle,
"GEOSFree_r");
101 if (!pfn_GEOS_init_r || !pfn_GEOS_finish_r || !pfn_GEOSisValidDetail_r ||
102 !pfn_GEOSGeomFromWKB_buf_r || !pfn_GEOSGeom_destroy_r || !pfn_GEOSFree_r) {
103 LOG(
WARNING) <<
"Failed to dynamically load required GEOS function pointers. Check "
104 "GEOS DSO version. Geometry validation unavailable.";
105 geos_can_validate =
false;
123 auto* context = pfn_GEOS_init_r();
125 auto* geom = pfn_GEOSGeomFromWKB_buf_r(context, wkb, wkb_size);
129 GEOSGeometry* location{};
131 result = pfn_GEOSisValidDetail_r(context, geom, flags, &reason, &location) != 0;
133 LOG(
WARNING) <<
"GEOS invalid reason: " << reason;
135 pfn_GEOSFree_r(context, reason);
136 pfn_GEOSGeom_destroy_r(context, location);
137 pfn_GEOSGeom_destroy_r(context, geom);
139 pfn_GEOS_finish_r(context);
147 namespace Geospatial {
bool geos_validate_wkb(const unsigned char *, const size_t)
bool geos_validation_available()