From: Mark Cave-Ayland Date: Tue, 9 Sep 2008 21:10:46 +0000 (+0000) Subject: Allow a flags parameter to be passed into the WKT parser to determine which consisten... X-Git-Tag: 1.4.0b1~755 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=742d9515ca0beba1628c934d72bf132f9de83d82;p=postgis Allow a flags parameter to be passed into the WKT parser to determine which consistency checks are performed out of polygon ring closure, minimum number of points and odd number of points. git-svn-id: http://svn.osgeo.org/postgis/trunk@2949 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/liblwgeom/liblwgeom.h b/liblwgeom/liblwgeom.h index ef0c18a46..7118bc319 100644 --- a/liblwgeom/liblwgeom.h +++ b/liblwgeom/liblwgeom.h @@ -1114,14 +1114,22 @@ extern LWCOLLECTION *lwcollection_segmentize2d(LWCOLLECTION *coll, double dist); extern uchar parse_hex(char *str); extern void deparse_hex(uchar str, char *result); +/* Parser check flags */ +#define PARSER_CHECK_MINPOINTS 1 +#define PARSER_CHECK_ODD 2 +#define PARSER_CHECK_CLOSURE 4 + +#define PARSER_CHECK_ALL (PARSER_CHECK_MINPOINTS | PARSER_CHECK_ODD | PARSER_CHECK_CLOSURE) + + /* Parser access routines */ extern char *lwgeom_to_ewkt(LWGEOM *lwgeom); extern char *lwgeom_to_hexwkb(LWGEOM *lwgeom, unsigned int byteorder); -extern LWGEOM *lwgeom_from_ewkb(uchar *ewkb, size_t ewkblen); +extern LWGEOM *lwgeom_from_ewkb(uchar *ewkb, size_t ewkblen, int flags); extern uchar *lwgeom_to_ewkb(LWGEOM *lwgeom, char byteorder, size_t *ewkblen); extern char *serialized_lwgeom_to_ewkt(uchar *serialized); -extern SERIALIZED_LWGEOM *serialized_lwgeom_from_ewkt(char *wkt_input); +extern SERIALIZED_LWGEOM *serialized_lwgeom_from_ewkt(char *wkt_input, int flags); extern char *serialized_lwgeom_to_hexwkb(uchar *serialized, unsigned int byteorder, size_t *size); extern char *serialized_lwgeom_to_ewkb(uchar *serialized, unsigned int byteorder, size_t *size); diff --git a/liblwgeom/lwgeom.c b/liblwgeom/lwgeom.c index a1f444490..3733e2301 100644 --- a/liblwgeom/lwgeom.c +++ b/liblwgeom/lwgeom.c @@ -508,7 +508,7 @@ lwgeom_to_ewkb(LWGEOM *lwgeom, char byteorder, size_t *outsize) * - deserialize it */ LWGEOM * -lwgeom_from_ewkb(uchar *ewkb, size_t size) +lwgeom_from_ewkb(uchar *ewkb, size_t size, int flags) { size_t hexewkblen = size*2; char *hexewkb; @@ -522,7 +522,7 @@ lwgeom_from_ewkb(uchar *ewkb, size_t size) hexewkb[hexewkblen] = '\0'; /* Rely on grammar parser to construct a LWGEOM */ - serialized_lwgeom = serialized_lwgeom_from_ewkt(hexewkb); + serialized_lwgeom = serialized_lwgeom_from_ewkt(hexewkb, flags); /* Free intermediate HEXified representation */ lwfree(hexewkb); @@ -543,9 +543,9 @@ lwgeom_from_ewkb(uchar *ewkb, size_t size) * Make a serialzed LWGEOM object from a WKT input string */ SERIALIZED_LWGEOM * -serialized_lwgeom_from_ewkt(char *wkt_input) +serialized_lwgeom_from_ewkt(char *wkt_input, int flags) { - SERIALIZED_LWGEOM *serialized_form = parse_lwg(wkt_input, + SERIALIZED_LWGEOM *serialized_form = parse_lwg(wkt_input, flags, lwalloc, lwerror); diff --git a/liblwgeom/lwgparse.c b/liblwgeom/lwgparse.c index 15c0c5c0c..6e7253c09 100644 --- a/liblwgeom/lwgparse.c +++ b/liblwgeom/lwgparse.c @@ -91,6 +91,16 @@ struct { } the_geom; tuple* free_list=0; + + +/* + * Parser global check flags - a bitmap of flags that determine which checks the parser will perform + * (see liblwgeom.h for the related PARSER_CHECK constants) + */ +int parser_check_flags; + + +/* Parser state flags - these are set automatically by the parser */ int minpoints; int checkclosed; @@ -102,6 +112,7 @@ int isodd; double *first_point=NULL; double *last_point=NULL; + /* External functions */ extern void init_parser(const char *); @@ -158,9 +169,9 @@ void read_wkb_ordinate_array(const char **b); void read_collection(const char **b, read_col_func f); void parse_wkb(const char **b); void alloc_wkb(const char *parser); -SERIALIZED_LWGEOM* parse_it(const char* geometry, allocator allocfunc, report_error errfunc); -SERIALIZED_LWGEOM* parse_lwg(const char* geometry, allocator allocfunc, report_error errfunc); -SERIALIZED_LWGEOM* parse_lwgi(const char* geometry, allocator allocfunc, report_error errfunc); +SERIALIZED_LWGEOM* parse_it(const char* geometry, int flags, allocator allocfunc, report_error errfunc); +SERIALIZED_LWGEOM* parse_lwg(const char* geometry, int flags, allocator allocfunc, report_error errfunc); +SERIALIZED_LWGEOM* parse_lwgi(const char* geometry, int flags, allocator allocfunc, report_error errfunc); void set_srid(double d_srid) @@ -269,20 +280,30 @@ pop(void) void popc(void) { + /* If the minimum point check has been enabled, perform it */ + if (parser_check_flags & PARSER_CHECK_MINPOINTS) { + if ( the_geom.stack->uu.nn.num < minpoints){ + error("geometry requires more points"); + } + } - if ( the_geom.stack->uu.nn.num < minpoints){ - error("geometry requires more points"); + /* If the odd number point check has been enabled, perform it */ + if (parser_check_flags & PARSER_CHECK_CLOSURE) { + if(isodd != -1 && the_geom.stack->uu.nn.num % 2 != isodd) { + error("geometry must have an odd number of points"); + } + } + + /* If the polygon closure check has been enabled, perform it */ + if (parser_check_flags & PARSER_CHECK_ODD) { + if ( checkclosed && first_point && last_point) { + if ( memcmp(first_point, last_point, + sizeof(double)*the_geom.ndims) ) + { + error("geometry contains non-closed rings"); + } + } } - if(isodd != -1 && the_geom.stack->uu.nn.num % 2 != isodd) { - error("geometry must have an odd number of points"); - } - if ( checkclosed && first_point && last_point) { - if ( memcmp(first_point, last_point, - sizeof(double)*the_geom.ndims) ) - { - error("geometry contains non-closed rings"); - } - } the_geom.stack = the_geom.stack->uu.nn.stack_next; } @@ -1106,7 +1127,7 @@ alloc_wkb(const char *parser) Parse a string and return a LW_GEOM */ SERIALIZED_LWGEOM * -parse_it(const char *geometry, allocator allocfunc, report_error errfunc) +parse_it(const char *geometry, int flags, allocator allocfunc, report_error errfunc) { LWDEBUGF(2, "parse_it: %s", geometry); @@ -1115,6 +1136,9 @@ parse_it(const char *geometry, allocator allocfunc, report_error errfunc) ferror_occured = 0; + /* Setup the inital parser flags */ + parser_check_flags = flags; + init_parser(geometry); lwg_parse_yyparse(); @@ -1128,17 +1152,17 @@ parse_it(const char *geometry, allocator allocfunc, report_error errfunc) } SERIALIZED_LWGEOM * -parse_lwg(const char* geometry,allocator allocfunc,report_error errfunc) +parse_lwg(const char* geometry, int flags, allocator allocfunc, report_error errfunc) { the_geom.lwgi=0; - return parse_it(geometry,allocfunc,errfunc); + return parse_it(geometry, flags, allocfunc, errfunc); } SERIALIZED_LWGEOM * -parse_lwgi(const char* geometry,allocator allocfunc,report_error errfunc) +parse_lwgi(const char* geometry, int flags, allocator allocfunc, report_error errfunc) { the_geom.lwgi=1; - return parse_it(geometry,allocfunc,errfunc); + return parse_it(geometry, flags, allocfunc, errfunc); } void diff --git a/liblwgeom/wktparse.h b/liblwgeom/wktparse.h index ebb61bacd..7a27d0c2b 100644 --- a/liblwgeom/wktparse.h +++ b/liblwgeom/wktparse.h @@ -96,8 +96,8 @@ void alloc_wkb(const char* parser); You are responsible for freeing the returned memory. */ -SERIALIZED_LWGEOM* parse_lwg(const char* wkt,allocator allocfunc,report_error errfunc); -SERIALIZED_LWGEOM* parse_lwgi(const char* wkt,allocator allocfunc,report_error errfunc); +SERIALIZED_LWGEOM* parse_lwg(const char* wkt, int flags, allocator allocfunc,report_error errfunc); +SERIALIZED_LWGEOM* parse_lwgi(const char* wkt, int flags, allocator allocfunc,report_error errfunc); char* unparse_WKT(uchar* serialized, allocator alloc,freeor free); char* unparse_WKB(uchar* serialized, allocator alloc,freeor free, char endian, size_t *outsize, uchar hexform); int lwg_parse_yyparse(void); diff --git a/lwgeom/lwgeom_gist.c b/lwgeom/lwgeom_gist.c index 75906c122..94d6201e7 100644 --- a/lwgeom/lwgeom_gist.c +++ b/lwgeom/lwgeom_gist.c @@ -746,8 +746,8 @@ lwgeom_rtree_leaf_consistent(BOX2DFLOAT4 *key, PG_FUNCTION_INFO_V1(LWGEOM_gist_decompress); Datum LWGEOM_gist_decompress(PG_FUNCTION_ARGS) { -#if POSTGIS_DEBUG_LEVEL >= 4 static unsigned int counter2 = 0; +#if POSTGIS_DEBUG_LEVEL >= 4 counter2++; #endif POSTGIS_DEBUGF(2, "GIST: LWGEOM_gist_decompress called %i",counter2); diff --git a/lwgeom/lwgeom_inout.c b/lwgeom/lwgeom_inout.c index 8ec4fbf91..aba81d3cf 100644 --- a/lwgeom/lwgeom_inout.c +++ b/lwgeom/lwgeom_inout.c @@ -68,7 +68,7 @@ Datum LWGEOM_in(PG_FUNCTION_ARGS) PG_LWGEOM *ret; /* will handle both HEXEWKB and EWKT */ - serialized_lwgeom = serialized_lwgeom_from_ewkt(str); + serialized_lwgeom = serialized_lwgeom_from_ewkt(str, PARSER_CHECK_ALL); lwgeom = lwgeom_deserialize(serialized_lwgeom->lwgeom); ret = pglwgeom_serialize(lwgeom); @@ -476,7 +476,7 @@ Datum parse_WKT_lwgeom(PG_FUNCTION_ARGS) POSTGIS_DEBUGF(3, "in parse_WKT_lwgeom with input: '%s'",wkt); - serialized_lwgeom = serialized_lwgeom_from_ewkt(wkt); + serialized_lwgeom = serialized_lwgeom_from_ewkt(wkt, PARSER_CHECK_ALL); lwgeom = lwgeom_deserialize(serialized_lwgeom->lwgeom); ret = pglwgeom_serialize(lwgeom); diff --git a/lwgeom/lwgeom_ogc.c b/lwgeom/lwgeom_ogc.c index 6d49ddc9e..9e099c840 100644 --- a/lwgeom/lwgeom_ogc.c +++ b/lwgeom/lwgeom_ogc.c @@ -1002,7 +1002,7 @@ Datum LWGEOM_from_text(PG_FUNCTION_ARGS) POSTGIS_DEBUGF(3, "wkt: [%s]", wkt); - serialized_lwgeom = serialized_lwgeom_from_ewkt(wkt); + serialized_lwgeom = serialized_lwgeom_from_ewkt(wkt, PARSER_CHECK_ALL); lwgeom = lwgeom_deserialize(serialized_lwgeom->lwgeom); if ( lwgeom->SRID != -1 || TYPE_GETZM(lwgeom->type) != 0 ) diff --git a/lwgeom/lwgeom_pg.c b/lwgeom/lwgeom_pg.c index 1324fcd7d..4b8bb9546 100644 --- a/lwgeom/lwgeom_pg.c +++ b/lwgeom/lwgeom_pg.c @@ -264,7 +264,7 @@ pglwgeom_from_ewkb(uchar *ewkb, size_t ewkblen) } hexewkb[hexewkblen] = '\0'; - serialized_lwgeom = serialized_lwgeom_from_ewkt(hexewkb); + serialized_lwgeom = serialized_lwgeom_from_ewkt(hexewkb, PARSER_CHECK_ALL); ret = (PG_LWGEOM *)palloc(serialized_lwgeom->size + VARHDRSZ); SET_VARSIZE(ret, serialized_lwgeom->size + VARHDRSZ);