From 8ce853731f843c43516449d66d7187ac16ab0280 Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Mon, 23 Aug 2004 10:49:08 +0000 Subject: [PATCH] Fixed a bug in serializedform length computation (for collection). git-svn-id: http://svn.osgeo.org/postgis/trunk@717 b70326c6-7e19-0410-871a-916f4a2858ee --- lwgeom/lwgeom_api.c | 192 +++++++++++++++++++++----------- lwgeom/lwgeom_functions_basic.c | 42 +++++-- 2 files changed, 159 insertions(+), 75 deletions(-) diff --git a/lwgeom/lwgeom_api.c b/lwgeom/lwgeom_api.c index 0f04f5680..12bb93930 100644 --- a/lwgeom/lwgeom_api.c +++ b/lwgeom/lwgeom_api.c @@ -873,13 +873,13 @@ BOX3D *lwline_findbbox(LWLINE *line) //find length of this serialized line uint32 lwline_findlength(char *serialized_line) { - int type = (unsigned char) serialized_line[0]; - uint32 result =1; //type - char *loc; - uint32 npoints; + int type = (unsigned char) serialized_line[0]; + uint32 result =1; //type + char *loc; + uint32 npoints; - if ( lwgeom_getType(type) != LINETYPE) - elog(ERROR,"lwline_findlength::attempt to find the length of a non-line"); + if ( lwgeom_getType(type) != LINETYPE) + elog(ERROR,"lwline_findlength::attempt to find the length of a non-line"); loc = serialized_line+1; @@ -1323,69 +1323,75 @@ BOX3D *lwpoly_findbbox(LWPOLY *poly) //find length of this serialized polygon uint32 lwpoly_findlength(char *serialized_poly) { - uint32 result = 1; // char type - uint32 nrings; - int ndims; - int t; - unsigned char type; - uint32 npoints; - char *loc; + uint32 result = 1; // char type + uint32 nrings; + int ndims; + int t; + unsigned char type; + uint32 npoints; + char *loc; - if (serialized_poly == NULL) - return -9999; + if (serialized_poly == NULL) + return -9999; - type = (unsigned char) serialized_poly[0]; - ndims = lwgeom_ndims(type); + type = (unsigned char) serialized_poly[0]; + ndims = lwgeom_ndims(type); - if ( lwgeom_getType(type) != POLYGONTYPE) - return -9999; + if ( lwgeom_getType(type) != POLYGONTYPE) + return -9999; loc = serialized_poly+1; if (lwgeom_hasBBOX(type)) { +#ifdef DEBUG + elog(NOTICE, "lwpoly_findlength: has bbox"); +#endif loc += sizeof(BOX2DFLOAT4); result +=sizeof(BOX2DFLOAT4); } - if ( lwgeom_hasSRID(type)) - { - loc +=4; // type + SRID - result += 4; - } + if ( lwgeom_hasSRID(type)) + { +#ifdef DEBUG + elog(NOTICE, "lwpoly_findlength: has srid"); +#endif + loc +=4; // type + SRID + result += 4; + } - nrings = get_uint32(loc); + nrings = get_uint32(loc); + loc +=4; + result +=4; + + + for (t =0;tsub_geoms = sub_geoms; + return result; } - else + + // its a GeometryCollection or multi* geometry + + if (lwgeom_hasSRID((unsigned char) serialized_form[0]) ) { - if (lwgeom_hasSRID((unsigned char) serialized_form[0]) ) - { - result->SRID= get_int32(loc); - loc += 4; - } - //its a GeometryCollection or multi* geometry - result->ngeometries = get_uint32(loc); - loc +=4; - sub_geoms = (char**) palloc(sizeof(char*) * result->ngeometries ); - result->sub_geoms = sub_geoms; - sub_geoms[0] = loc; - for (t=1;tngeometries; t++) - { - int sub_length = lwgeom_seralizedformlength(sub_geoms[t-1], -1);//-1 = entire object - sub_geoms[t] = sub_geoms[t-1] + sub_length; - } + result->SRID= get_int32(loc); + loc += 4; + } + + result->ngeometries = get_uint32(loc); + loc +=4; +#ifdef DEBUG + elog(NOTICE, "lwgeom_inspect: geometry is a collection of %d elements", + result->ngeometries); +#endif + + sub_geoms = (char**) palloc(sizeof(char*) * result->ngeometries ); + result->sub_geoms = sub_geoms; + sub_geoms[0] = loc; +#ifdef DEBUG + elog(NOTICE, "subgeom[0] @ %i", sub_geoms[0]); +#endif + for (t=1;tngeometries; t++) + { + int sub_length = lwgeom_seralizedformlength(sub_geoms[t-1], -1);//-1 = entire object + sub_geoms[t] = sub_geoms[t-1] + sub_length; +#ifdef DEBUG + elog(NOTICE, "subgeom[%d] @ %i (sub_length: %d)", + t, sub_geoms[t], sub_length); +#endif } return result; @@ -1858,27 +1877,57 @@ int lwgeom_seralizedformlength_simple(char *serialized_form) int result = 1; //"type" if (type == POINTTYPE) + { +#ifdef DEBUG + elog(NOTICE, "lwgeom_seralizedformlength_simple: is a point"); +#endif return lwpoint_findlength(serialized_form); + } else if (type == LINETYPE) + { +#ifdef DEBUG + elog(NOTICE, "lwgeom_seralizedformlength_simple: is a line"); +#endif return lwline_findlength(serialized_form); + } else if (type == POLYGONTYPE) + { +#ifdef DEBUG + elog(NOTICE, "lwgeom_seralizedformlength_simple: is a polygon"); +#endif return lwpoly_findlength(serialized_form); + } - //handle all the multi* and geometrycollections the same - //NOTE: for a geometry collection of GC of GC of GC we will be recursing... + if ( type == 0 ) + { + elog(ERROR, "lwgeom_seralizedformlength_simple called with unknown-typed serialized geometry"); + return 0; + } + //handle all the multi* and geometrycollections the same + //NOTE: for a geometry collection of GC of GC of GC we will be recursing... +#ifdef DEBUG + elog(NOTICE, "lwgeom_seralizedformlength_simple called on a geoemtry with type %d", type); +#endif loc = serialized_form+1; if (lwgeom_hasBBOX((unsigned char) serialized_form[0])) { +#ifdef DEBUG + elog(NOTICE, "lwgeom_seralizedformlength_simple: has bbox"); +#endif + loc += sizeof(BOX2DFLOAT4); result +=sizeof(BOX2DFLOAT4); } if (lwgeom_hasSRID( (unsigned char) serialized_form[0]) ) { +#ifdef DEBUG + elog(NOTICE, "lwgeom_seralizedformlength_simple: has srid"); +#endif result +=4; loc +=4; } @@ -1886,14 +1935,25 @@ int lwgeom_seralizedformlength_simple(char *serialized_form) ngeoms = get_uint32(loc); loc +=4; + result += 4; // numgeoms + +#ifdef DEBUG + elog(NOTICE, "lwgeom_seralizedformlength_simple called on a geoemtry with %d elems (result so far: %d)", ngeoms, result); +#endif for (t=0;tsize; + int32 computed_size = lwgeom_seralizedformlength_simple(SERIALIZED_FORM(geom)); + computed_size += 4; // varlena size + if ( size != computed_size ) + { + elog(NOTICE, "varlena size (%d) != computed size+4 (%d)", + size, computed_size); + } + PG_FREE_IF_COPY(geom,0); PG_RETURN_INT32(size); } @@ -156,8 +164,9 @@ Datum lwgeom_mem_size(PG_FUNCTION_ARGS) * LWGEOM object */ char * -lwgeom_summary_recursive(char *serialized) +lwgeom_summary_recursive(char *serialized, int offset) { + static int idx = 0; LWGEOM_INSPECTED *inspected; char *result; char *ptr; @@ -169,21 +178,34 @@ lwgeom_summary_recursive(char *serialized) result = palloc(1); result[0] = '\0'; + if ( offset == 0 ) idx = 0; + inspected = lwgeom_inspect(serialized); + + if (0) { + size += 57; + result = repalloc(result,size); + sprintf(tmp, + "Geometry (inspected) contains %i subgeoms\n", + inspected->ngeometries); + strcat(result,tmp); + } + //now have to do a scan of each object for (j=0; jngeometries; j++) { LWLINE *line=NULL; LWPOINT *point=NULL; LWPOLY *poly=NULL; - char *subgeom; + char *subgeom=NULL; point = lwgeom_getpoint_inspected(inspected,j); if (point !=NULL) { size += 30; result = repalloc(result,size); - sprintf(tmp,"Object %i is a POINT()\n",j); + sprintf(tmp,"Object %i is a POINT()\n", + idx++); strcat(result,tmp); continue; } @@ -193,7 +215,8 @@ lwgeom_summary_recursive(char *serialized) { size += 57*(poly->nrings+1); result = repalloc(result,size); - sprintf(tmp,"Object %i is a POLYGON() with %i rings\n",j,poly->nrings); + sprintf(tmp,"Object %i is a POLYGON() with %i rings\n", + idx++, poly->nrings); strcat(result,tmp); for (i=0; inrings;i++) { @@ -211,7 +234,7 @@ lwgeom_summary_recursive(char *serialized) result = repalloc(result,size); sprintf(tmp, "Object %i is a LINESTRING() with %i points\n", - j, line->points->npoints); + idx++, line->points->npoints); strcat(result,tmp); continue; } @@ -219,7 +242,7 @@ lwgeom_summary_recursive(char *serialized) subgeom = lwgeom_getsubgeometry_inspected(inspected, j); if ( subgeom != NULL ) { - ptr = lwgeom_summary_recursive(subgeom); + ptr = lwgeom_summary_recursive(subgeom, 1); size += strlen(ptr); result = repalloc(result,size); strcat(result, ptr); @@ -231,6 +254,7 @@ lwgeom_summary_recursive(char *serialized) } } + pfree_inspected(inspected); return result; } @@ -242,7 +266,7 @@ Datum lwgeom_summary(PG_FUNCTION_ARGS) char *result; text *mytext; - result = lwgeom_summary_recursive(SERIALIZED_FORM(geom)); + result = lwgeom_summary_recursive(SERIALIZED_FORM(geom), 0); // create a text obj to return mytext = (text *) palloc(VARHDRSZ + strlen(result) ); -- 2.40.0