| """ |
| Error checking functions for GEOS ctypes prototype functions. |
| """ |
| import os |
| from ctypes import c_void_p, string_at, CDLL |
| from django.contrib.gis.geos.error import GEOSException |
| from django.contrib.gis.geos.libgeos import GEOS_VERSION |
| from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc |
| |
| # Getting the `free` routine used to free the memory allocated for |
| # string pointers returned by GEOS. |
| if GEOS_VERSION >= (3, 1, 1): |
| # In versions 3.1.1 and above, `GEOSFree` was added to the C API |
| # because `free` isn't always available on all platforms. |
| free = GEOSFunc('GEOSFree') |
| free.argtypes = [c_void_p] |
| free.restype = None |
| else: |
| # Getting the `free` routine from the C library of the platform. |
| if os.name == 'nt': |
| # On NT, use the MS C library. |
| libc = CDLL('msvcrt') |
| else: |
| # On POSIX platforms C library is obtained by passing None into `CDLL`. |
| libc = CDLL(None) |
| free = libc.free |
| |
| ### ctypes error checking routines ### |
| def last_arg_byref(args): |
| "Returns the last C argument's value by reference." |
| return args[-1]._obj.value |
| |
| def check_dbl(result, func, cargs): |
| "Checks the status code and returns the double value passed in by reference." |
| # Checking the status code |
| if result != 1: return None |
| # Double passed in by reference, return its value. |
| return last_arg_byref(cargs) |
| |
| def check_geom(result, func, cargs): |
| "Error checking on routines that return Geometries." |
| if not result: |
| raise GEOSException('Error encountered checking Geometry returned from GEOS C function "%s".' % func.__name__) |
| return result |
| |
| def check_minus_one(result, func, cargs): |
| "Error checking on routines that should not return -1." |
| if result == -1: |
| raise GEOSException('Error encountered in GEOS C function "%s".' % func.__name__) |
| else: |
| return result |
| |
| def check_predicate(result, func, cargs): |
| "Error checking for unary/binary predicate functions." |
| val = ord(result) # getting the ordinal from the character |
| if val == 1: return True |
| elif val == 0: return False |
| else: |
| raise GEOSException('Error encountered on GEOS C predicate function "%s".' % func.__name__) |
| |
| def check_sized_string(result, func, cargs): |
| """ |
| Error checking for routines that return explicitly sized strings. |
| |
| This frees the memory allocated by GEOS at the result pointer. |
| """ |
| if not result: |
| raise GEOSException('Invalid string pointer returned by GEOS C function "%s"' % func.__name__) |
| # A c_size_t object is passed in by reference for the second |
| # argument on these routines, and its needed to determine the |
| # correct size. |
| s = string_at(result, last_arg_byref(cargs)) |
| # Freeing the memory allocated within GEOS |
| free(result) |
| return s |
| |
| def check_string(result, func, cargs): |
| """ |
| Error checking for routines that return strings. |
| |
| This frees the memory allocated by GEOS at the result pointer. |
| """ |
| if not result: raise GEOSException('Error encountered checking string return value in GEOS C function "%s".' % func.__name__) |
| # Getting the string value at the pointer address. |
| s = string_at(result) |
| # Freeing the memory allocated within GEOS |
| free(result) |
| return s |
| |
| def check_zero(result, func, cargs): |
| "Error checking on routines that should not return 0." |
| if result == 0: |
| raise GEOSException('Error encountered in GEOS C function "%s".' % func.__name__) |
| else: |
| return result |