[postgis-tickets] r16224 - Rewrite to use stringbuffer instead of the mess of sprintfs

Regina Obe lr at pcorp.us
Mon Jan 8 09:09:10 PST 2018


Author: robe
Date: 2018-01-08 09:09:09 -0800 (Mon, 08 Jan 2018)
New Revision: 16224

Modified:
   trunk/liblwgeom/lwout_x3d.c
   trunk/liblwgeom/lwout_x3d.h
Log:
Rewrite to use stringbuffer instead of the mess of sprintfs
Closes #3974

Modified: trunk/liblwgeom/lwout_x3d.c
===================================================================
--- trunk/liblwgeom/lwout_x3d.c	2018-01-05 23:43:58 UTC (rev 16223)
+++ trunk/liblwgeom/lwout_x3d.c	2018-01-08 17:09:09 UTC (rev 16224)
@@ -31,12 +31,13 @@
 /*
  * VERSION X3D 3.0.2 http://www.web3d.org/specifications/x3d-3.0.dtd
  */
-
-/* takes a GEOMETRY and returns an X3D representation */
-extern char *
+/* takes a GEOMETRY and returns a X3D representation */
+char*
 lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid)
 {
-	int type = geom->type;
+	stringbuffer_t *sb;
+	int rv;
+	char *result;
 
 	/* Empty string for empties */
 	if( lwgeom_is_empty(geom) )
@@ -47,13 +48,33 @@
 		return ret;
 	}
 
+	sb = stringbuffer_create();
+	rv = lwgeom_to_x3d3_sb(geom, srs, precision, opts, defid, sb);
+
+	if ( rv == LW_FAILURE )
+	{
+		stringbuffer_destroy(sb);
+		return NULL;
+	}
+
+	result = stringbuffer_getstringcopy(sb);
+	stringbuffer_destroy(sb);
+
+	return result;
+}
+/* takes a GEOMETRY and appends to string buffer the x3d output */
+static int
+lwgeom_to_x3d3_sb(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
+{
+	int type = geom->type;
+
 	switch (type)
 	{
 	case POINTTYPE:
-		return asx3d3_point((LWPOINT*)geom, srs, precision, opts, defid);
+		return asx3d3_point_sb((LWPOINT*)geom, srs, precision, opts, defid, sb);
 
 	case LINETYPE:
-		return asx3d3_line((LWLINE*)geom, srs, precision, opts, defid);
+		return asx3d3_line_sb((LWLINE*)geom, srs, precision, opts, defid, sb);
 
 	case POLYGONTYPE:
 	{
@@ -61,141 +82,52 @@
 		* seems like the simplest way to go so treat just like a mulitpolygon
 		*/
 		LWCOLLECTION *tmp = (LWCOLLECTION*)lwgeom_as_multi(geom);
-		char *ret = asx3d3_multi(tmp, srs, precision, opts, defid);
+		asx3d3_multi_sb(tmp, srs, precision, opts, defid, sb);
 		lwcollection_free(tmp);
-		return ret;
+		return LW_SUCCESS;
 	}
 
 	case TRIANGLETYPE:
-		return asx3d3_triangle((LWTRIANGLE*)geom, srs, precision, opts, defid);
+		return asx3d3_triangle_sb((LWTRIANGLE*)geom, srs, precision, opts, defid, sb);
 
 	case MULTIPOINTTYPE:
 	case MULTILINETYPE:
 	case MULTIPOLYGONTYPE:
-		return asx3d3_multi((LWCOLLECTION*)geom, srs, precision, opts, defid);
+		return asx3d3_multi_sb((LWCOLLECTION*)geom, srs, precision, opts, defid, sb);
 
 	case POLYHEDRALSURFACETYPE:
-		return asx3d3_psurface((LWPSURFACE*)geom, srs, precision, opts, defid);
+		return asx3d3_psurface_sb((LWPSURFACE*)geom, srs, precision, opts, defid, sb);
 
 	case TINTYPE:
-		return asx3d3_tin((LWTIN*)geom, srs, precision, opts, defid);
+		return asx3d3_tin_sb((LWTIN*)geom, srs, precision, opts, defid, sb);
 
 	case COLLECTIONTYPE:
-		return asx3d3_collection((LWCOLLECTION*)geom, srs, precision, opts, defid);
+		return asx3d3_collection_sb((LWCOLLECTION*)geom, srs, precision, opts, defid, sb);
 
 	default:
 		lwerror("lwgeom_to_x3d3: '%s' geometry type not supported", lwtype_name(type));
-		return NULL;
+		return LW_FAILURE;
 	}
 }
 
-static size_t
-asx3d3_point_size(const LWPOINT *point, char *srs, int precision, int opts, const char *defid)
+static int
+asx3d3_point_sb(const LWPOINT *point, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
 {
-	int size;
-	/* size_t defidlen = strlen(defid); */
-
-	size = pointArray_X3Dsize(point->point, precision);
-	/* size += ( sizeof("<point><pos>/") + (defidlen*2) ) * 2; */
-	/* if (srs)     size += strlen(srs) + sizeof(" srsName=.."); */
-	return size;
+	/** for point we just output the coordinates **/
+	return ptarray_to_x3d3_sb(point->point, precision, opts, 0, sb);
 }
 
-static size_t
-asx3d3_point_buf(const LWPOINT *point, char *srs, char *output, int precision, int opts, const char *defid)
+static int
+asx3d3_line_coords_sb(const LWLINE *line, int precision, int opts, stringbuffer_t *sb)
 {
-	char *ptr = output;
-	/* int dimension=2; */
-
-	/* if (FLAGS_GET_Z(point->flags)) dimension = 3; */
-	/*	if ( srs )
-		{
-			ptr += sprintf(ptr, "<%sPoint srsName=\"%s\">", defid, srs);
-		}
-		else*/
-	/* ptr += sprintf(ptr, "%s", defid); */
-
-	/* ptr += sprintf(ptr, "<%spos>", defid); */
-	ptr += pointArray_toX3D3(point->point, ptr, precision, opts, 0);
-	/* ptr += sprintf(ptr, "</%spos></%sPoint>", defid, defid); */
-
-	return (ptr-output);
+	return ptarray_to_x3d3_sb(line->points, precision, opts, lwline_is_closed(line), sb);
 }
 
-static char *
-asx3d3_point(const LWPOINT *point, char *srs, int precision, int opts, const char *defid)
+/* Calculate the coordIndex property of the IndexedLineSet for the multilinestring
+and add to string buffer */
+static int
+asx3d3_mline_coordindex_sb(const LWMLINE *mgeom, stringbuffer_t *sb)
 {
-	char *output;
-	int size;
-
-	size = asx3d3_point_size(point, srs, precision, opts, defid);
-	output = lwalloc(size);
-	asx3d3_point_buf(point, srs, output, precision, opts, defid);
-	return output;
-}
-
-
-static size_t
-asx3d3_line_size(const LWLINE *line, char *srs, int precision, int opts, const char *defid)
-{
-	int size;
-	size_t defidlen = strlen(defid);
-
-	size = pointArray_X3Dsize(line->points, precision)*2;
-
-	if ( X3D_USE_GEOCOORDS(opts) ) {
-			size += (
-	            sizeof("<LineSet vertexCount=''><GeoCoordinate geoSystem='\"GD\" \"WE\" \"longitude_first\"' point='' /></LineSet>")  + defidlen
-	        ) * 2;
-	}
-	else {
-		size += (
-		            sizeof("<LineSet vertexCount=''><Coordinate point='' /></LineSet>")  + defidlen
-		        ) * 2;
-	}
-
-	/* if (srs)     size += strlen(srs) + sizeof(" srsName=.."); */
-	return size;
-}
-
-static size_t
-asx3d3_line_buf(const LWLINE *line, char *srs, char *output, int precision, int opts, const char *defid)
-{
-	char *ptr=output;
-	/* int dimension=2; */
-	POINTARRAY *pa;
-
-
-	/* if (FLAGS_GET_Z(line->flags)) dimension = 3; */
-
-	pa = line->points;
-	ptr += sprintf(ptr, "<LineSet %s vertexCount='%d'>", defid, pa->npoints);
-
-	if ( X3D_USE_GEOCOORDS(opts) ) ptr += sprintf(ptr, "<GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ( (opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
-	else
-		ptr += sprintf(ptr, "<Coordinate point='");
-	ptr += pointArray_toX3D3(line->points, ptr, precision, opts, lwline_is_closed((LWLINE *) line));
-
-	ptr += sprintf(ptr, "' />");
-
-	ptr += sprintf(ptr, "</LineSet>");
-	return (ptr-output);
-}
-
-static size_t
-asx3d3_line_coords(const LWLINE *line, char *output, int precision, int opts)
-{
-	char *ptr=output;
-	/* ptr += sprintf(ptr, ""); */
-	ptr += pointArray_toX3D3(line->points, ptr, precision, opts, lwline_is_closed(line));
-	return (ptr-output);
-}
-
-/* Calculate the coordIndex property of the IndexedLineSet for the multilinestring */
-static size_t
-asx3d3_mline_coordindex(const LWMLINE *mgeom, char *output)
-{
-	char *ptr=output;
 	LWLINE *geom;
 	int i, j, k, si;
 	POINTARRAY *pa;
@@ -212,36 +144,35 @@
 		{
 			if (k)
 			{
-				ptr += sprintf(ptr, " ");
+				stringbuffer_aprintf(sb, " ");
 			}
 			/** if the linestring is closed, we put the start point index
 			*   for the last vertex to denote use first point
 			*    and don't increment the index **/
 			if (!lwline_is_closed(geom) || k < (np -1) )
 			{
-				ptr += sprintf(ptr, "%d", j);
+				stringbuffer_aprintf(sb, "%d", j);
 				j += 1;
 			}
 			else
 			{
-				ptr += sprintf(ptr,"%d", si);
+				stringbuffer_aprintf(sb,"%d", si);
 			}
 		}
 		if (i < (mgeom->ngeoms - 1) )
 		{
-			ptr += sprintf(ptr, " -1 "); /* separator for each linestring */
+			stringbuffer_aprintf(sb, " -1 "); /* separator for each linestring */
 		}
 	}
-	return (ptr-output);
+	return LW_SUCCESS;
 }
 
 /* Calculate the coordIndex property of the IndexedLineSet for a multipolygon
     This is not ideal -- would be really nice to just share this function with psurf,
     but I'm not smart enough to do that yet*/
-static size_t
-asx3d3_mpoly_coordindex(const LWMPOLY *psur, char *output)
+static int
+asx3d3_mpoly_coordindex_sb(const LWMPOLY *psur, stringbuffer_t *sb)
 {
-	char *ptr=output;
 	LWPOLY *patch;
 	int i, j, k, l;
 	int np;
@@ -256,9 +187,9 @@
 			{
 				if (k)
 				{
-					ptr += sprintf(ptr, " ");
+					stringbuffer_aprintf(sb,  " ");
 				}
-				ptr += sprintf(ptr, "%d", (j + k));
+				stringbuffer_aprintf(sb,  "%d", (j + k));
 			}
 			j += k;
 			if (l < (patch->nrings - 1) )
@@ -271,155 +202,75 @@
 				*  For now will leave it as polygons stacked on top of each other -- which is what we are doing here and perhaps an option
 				*  to color differently.  It's not ideal but the alternative sounds complicated.
 				**/
-				ptr += sprintf(ptr, " -1 "); /* separator for each inner ring. Ideally we should probably triangulate and cut around as others do */
+				stringbuffer_aprintf(sb,  " -1 "); /* separator for each inner ring. Ideally we should probably triangulate and cut around as others do */
 			}
 		}
 		if (i < (psur->ngeoms - 1) )
 		{
-			ptr += sprintf(ptr, " -1 "); /* separator for each subgeom */
+			stringbuffer_aprintf(sb,  " -1 "); /* separator for each subgeom */
 		}
 	}
-	return (ptr-output);
+	return LW_SUCCESS;
 }
 
 /** Return the linestring as an X3D LineSet */
-static char *
-asx3d3_line(const LWLINE *line, char *srs, int precision, int opts, const char *defid)
+static int
+asx3d3_line_sb(const LWLINE *line, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
 {
-	char *output;
-	int size;
 
-	size = sizeof("<LineSet><CoordIndex ='' /></LineSet>") + asx3d3_line_size(line, srs, precision, opts, defid);
-	output = lwalloc(size);
-	asx3d3_line_buf(line, srs, output, precision, opts, defid);
-	return output;
-}
+	/* int dimension=2; */
+	POINTARRAY *pa;
 
-/** Compute the string space needed for the IndexedFaceSet representation of the polygon **/
-static size_t
-asx3d3_poly_size(const LWPOLY *poly,  char *srs, int precision, int opts, const char *defid)
-{
-	size_t size;
-	size_t defidlen = strlen(defid);
-	int i;
 
-	size = ( sizeof("<IndexedFaceSet></IndexedFaceSet>") + (defidlen*3) ) * 2 + 6 * (poly->nrings - 1);
+	/* if (FLAGS_GET_Z(line->flags)) dimension = 3; */
 
-	for (i=0; i<poly->nrings; i++)
-		size += pointArray_X3Dsize(poly->rings[i], precision);
+	pa = line->points;
+	stringbuffer_aprintf(sb, "<LineSet %s vertexCount='%d'>", defid, pa->npoints);
 
-	return size;
-}
+	if ( X3D_USE_GEOCOORDS(opts) ) stringbuffer_aprintf(sb, "<GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ( (opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
+	else
+		stringbuffer_aprintf(sb, "<Coordinate point='");
 
-/** Compute the X3D coordinates of the polygon **/
-static size_t
-asx3d3_poly_buf(const LWPOLY *poly, char *srs, char *output, int precision, int opts, int is_patch, const char *defid)
-{
-	int i;
-	char *ptr=output;
+	ptarray_to_x3d3_sb(line->points, precision, opts, lwline_is_closed((LWLINE *) line), sb);
 
-	ptr += pointArray_toX3D3(poly->rings[0], ptr, precision, opts, 1);
-	for (i=1; i<poly->nrings; i++)
-	{
-		ptr += sprintf(ptr, " "); /* inner ring points start */
-		ptr += pointArray_toX3D3(poly->rings[i], ptr, precision, opts,1);
-	}
-	return (ptr-output);
-}
 
-static size_t
-asx3d3_triangle_size(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid)
-{
-	size_t size;
-	size_t defidlen = strlen(defid);
+	stringbuffer_aprintf(sb, "' />");
 
-	/** 6 for the 3 sides and space to separate each side **/
-	size = sizeof("<IndexedTriangleSet index=''></IndexedTriangleSet>") + defidlen + 6;
-	size += pointArray_X3Dsize(triangle->points, precision);
-
-	return size;
+	return stringbuffer_aprintf(sb, "</LineSet>");
 }
 
-static size_t
-asx3d3_triangle_buf(const LWTRIANGLE *triangle, char *srs, char *output, int precision, int opts, const char *defid)
+/** Compute the X3D coordinates of the polygon and add to string buffer **/
+static int
+asx3d3_poly_sb(const LWPOLY *poly, char *srs, int precision, int opts, int is_patch, const char *defid, stringbuffer_t *sb)
 {
-	char *ptr=output;
-	ptr += pointArray_toX3D3(triangle->points, ptr, precision, opts, 1);
-
-	return (ptr-output);
-}
-
-static char *
-asx3d3_triangle(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid)
-{
-	char *output;
-	int size;
-
-	size = asx3d3_triangle_size(triangle, srs, precision, opts, defid);
-	output = lwalloc(size);
-	asx3d3_triangle_buf(triangle, srs, output, precision, opts, defid);
-	return output;
-}
-
-
-/**
- * Compute max size required for X3D version of this
- * inspected geometry. Will recurse when needed.
- * Don't call this with single-geoms inspected.
- */
-static size_t
-asx3d3_multi_size(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid)
-{
 	int i;
-	size_t size;
-	size_t defidlen = strlen(defid);
-	LWGEOM *subgeom;
-
-	/* the longest possible multi version needs to hold DEF=defid and coordinate breakout */
-	if ( X3D_USE_GEOCOORDS(opts) )
-		size = sizeof("<PointSet><GeoCoordinate geoSystem='\"GD\" \"WE\" \"longitude_first\"' point='' /></PointSet>");
-	else
-		size = sizeof("<PointSet><Coordinate point='' /></PointSet>") + defidlen;
-
-
-	/* if ( srs ) size += strlen(srs) + sizeof(" srsName=.."); */
-
-	for (i=0; i<col->ngeoms; i++)
+	for (i=0; i<poly->nrings; i++)
 	{
-		subgeom = col->geoms[i];
-		if (subgeom->type == POINTTYPE)
-		{
-			/* size += ( sizeof("point=''") + defidlen ) * 2; */
-			size += asx3d3_point_size((LWPOINT*)subgeom, 0, precision, opts, defid);
-		}
-		else if (subgeom->type == LINETYPE)
-		{
-			/* size += ( sizeof("<curveMember>/") + defidlen ) * 2; */
-			size += asx3d3_line_size((LWLINE*)subgeom, 0, precision, opts, defid);
-		}
-		else if (subgeom->type == POLYGONTYPE)
-		{
-			/* size += ( sizeof("<surfaceMember>/") + defidlen ) * 2; */
-			size += asx3d3_poly_size((LWPOLY*)subgeom, 0, precision, opts, defid);
-		}
+		if (i) stringbuffer_aprintf(sb, " "); /* inner ring points start */
+		ptarray_to_x3d3_sb(poly->rings[i], precision, opts, 1, sb);
 	}
+	return LW_SUCCESS;
+}
 
-	return size;
+static int
+asx3d3_triangle_sb(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
+{
+	return  ptarray_to_x3d3_sb(triangle->points, precision, opts, 1, sb);
 }
 
+
 /*
  * Don't call this with single-geoms inspected!
  */
-static size_t
-asx3d3_multi_buf(const LWCOLLECTION *col, char *srs, char *output, int precision, int opts, const char *defid)
+static int
+asx3d3_multi_sb(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
 {
-	char *ptr, *x3dtype;
+	char *x3dtype;
 	int i;
 	int dimension=2;
 
 	if (FLAGS_GET_Z(col->flags)) dimension = 3;
 	LWGEOM *subgeom;
-	ptr = output;
 	x3dtype="";
 
 
@@ -429,23 +280,23 @@
             x3dtype = "PointSet";
             if ( dimension == 2 ){ /** Use Polypoint2D instead **/
                 x3dtype = "Polypoint2D";
-                ptr += sprintf(ptr, "<%s %s point='", x3dtype, defid);
+                stringbuffer_aprintf(sb, "<%s %s point='", x3dtype, defid);
             }
             else {
-                ptr += sprintf(ptr, "<%s %s>", x3dtype, defid);
+                stringbuffer_aprintf(sb, "<%s %s>", x3dtype, defid);
             }
             break;
         case MULTILINETYPE:
             x3dtype = "IndexedLineSet";
-            ptr += sprintf(ptr, "<%s %s coordIndex='", x3dtype, defid);
-            ptr += asx3d3_mline_coordindex((const LWMLINE *)col, ptr);
-            ptr += sprintf(ptr, "'>");
+            stringbuffer_aprintf(sb, "<%s %s coordIndex='", x3dtype, defid);
+            asx3d3_mline_coordindex_sb((const LWMLINE *)col, sb);
+            stringbuffer_aprintf(sb, "'>");
             break;
         case MULTIPOLYGONTYPE:
             x3dtype = "IndexedFaceSet";
-            ptr += sprintf(ptr, "<%s %s convex='false' coordIndex='", x3dtype, defid);
-            ptr += asx3d3_mpoly_coordindex((const LWMPOLY *)col, ptr);
-            ptr += sprintf(ptr, "'>");
+            stringbuffer_aprintf(sb, "<%s %s convex='false' coordIndex='", x3dtype, defid);
+            asx3d3_mpoly_coordindex_sb((const LWMPOLY *)col, sb);
+            stringbuffer_aprintf(sb, "'>");
             break;
         default:
             lwerror("asx3d3_multi_buf: '%s' geometry type not supported", lwtype_name(col->type));
@@ -453,9 +304,9 @@
     }
     if (dimension == 3){
 		if ( X3D_USE_GEOCOORDS(opts) )
-			ptr += sprintf(ptr, "<GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ((opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
+			stringbuffer_aprintf(sb, "<GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ((opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
 		else
-        	ptr += sprintf(ptr, "<Coordinate point='");
+        	stringbuffer_aprintf(sb, "<Coordinate point='");
     }
 
 	for (i=0; i<col->ngeoms; i++)
@@ -463,82 +314,44 @@
 		subgeom = col->geoms[i];
 		if (subgeom->type == POINTTYPE)
 		{
-			ptr += asx3d3_point_buf((LWPOINT*)subgeom, 0, ptr, precision, opts, defid);
-			ptr += sprintf(ptr, " ");
+			asx3d3_point_sb((LWPOINT*)subgeom, 0, precision, opts, defid, sb);
+			stringbuffer_aprintf(sb, " ");
 		}
 		else if (subgeom->type == LINETYPE)
 		{
-			ptr += asx3d3_line_coords((LWLINE*)subgeom, ptr, precision, opts);
-			ptr += sprintf(ptr, " ");
+			asx3d3_line_coords_sb((LWLINE*)subgeom, precision, opts, sb);
+			stringbuffer_aprintf(sb, " ");
 		}
 		else if (subgeom->type == POLYGONTYPE)
 		{
-			ptr += asx3d3_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, opts, 0, defid);
-			ptr += sprintf(ptr, " ");
+			asx3d3_poly_sb((LWPOLY*)subgeom, 0, precision, opts, 0, defid, sb);
+			stringbuffer_aprintf(sb, " ");
 		}
 	}
 
 	/* Close outmost tag */
 	if (dimension == 3){
-	    ptr += sprintf(ptr, "' /></%s>", x3dtype);
+		stringbuffer_aprintf(sb, "' /></%s>", x3dtype);
 	}
-	else { ptr += sprintf(ptr, "' />"); }
-	return (ptr-output);
-}
+	else { stringbuffer_aprintf(sb, "' />"); }
+	return LW_SUCCESS;
 
-/*
- * Don't call this with single-geoms inspected!
- */
-static char *
-asx3d3_multi(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid)
-{
-	char *x3d;
-	size_t size;
-
-	size = asx3d3_multi_size(col, srs, precision, opts, defid);
-	x3d = lwalloc(size);
-	asx3d3_multi_buf(col, srs, x3d, precision, opts, defid);
-	return x3d;
 }
 
-
-static size_t
-asx3d3_psurface_size(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid)
-{
-	int i;
-	size_t size;
-	size_t defidlen = strlen(defid);
-
-	if ( X3D_USE_GEOCOORDS(opts) ) size = sizeof("<IndexedFaceSet convex='false' coordIndex=''><GeoCoordinate geoSystem='\"GD\" \"WE\" \"longitude_first\"' point='' />") + defidlen;
-	else size = sizeof("<IndexedFaceSet convex='false' coordIndex=''><Coordinate point='' />") + defidlen;
-
-
-	for (i=0; i<psur->ngeoms; i++)
-	{
-		size += asx3d3_poly_size(psur->geoms[i], 0, precision, opts, defid)*5; /** need to make space for coordIndex values too including -1 separating each poly**/
-	}
-
-	return size;
-}
-
-
 /*
  * Don't call this with single-geoms inspected!
  */
-static size_t
-asx3d3_psurface_buf(const LWPSURFACE *psur, char *srs, char *output, int precision, int opts, const char *defid)
+static int
+asx3d3_psurface_sb(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
 {
-	char *ptr;
 	int i;
 	int j;
 	int k;
 	int np;
 	LWPOLY *patch;
 
-	ptr = output;
-
 	/* Open outmost tag */
-	ptr += sprintf(ptr, "<IndexedFaceSet convex='false' %s coordIndex='",defid);
+	stringbuffer_aprintf(sb, "<IndexedFaceSet convex='false' %s coordIndex='",defid);
 
 	j = 0;
 	for (i=0; i<psur->ngeoms; i++)
@@ -549,281 +362,146 @@
 		{
 			if (k)
 			{
-				ptr += sprintf(ptr, " ");
+				stringbuffer_aprintf(sb, " ");
 			}
-			ptr += sprintf(ptr, "%d", (j + k));
+			stringbuffer_aprintf(sb,"%d", (j + k));
 		}
 		if (i < (psur->ngeoms - 1) )
 		{
-			ptr += sprintf(ptr, " -1 "); /* separator for each subgeom */
+			stringbuffer_aprintf(sb, " -1 "); /* separator for each subgeom */
 		}
 		j += k;
 	}
 
 	if ( X3D_USE_GEOCOORDS(opts) )
-		ptr += sprintf(ptr, "'><GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ( (opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
-	else ptr += sprintf(ptr, "'><Coordinate point='");
+		stringbuffer_aprintf(sb, "'><GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='",
+			( (opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
+	else stringbuffer_aprintf(sb, "'><Coordinate point='");
 
 	for (i=0; i<psur->ngeoms; i++)
 	{
-		ptr += asx3d3_poly_buf(psur->geoms[i], 0, ptr, precision, opts, 1, defid);
+		asx3d3_poly_sb(psur->geoms[i], srs, precision, opts, 1, defid, sb);
 		if (i < (psur->ngeoms - 1) )
 		{
-			ptr += sprintf(ptr, " "); /* only add a trailing space if its not the last polygon in the set */
+			stringbuffer_aprintf(sb, " "); /* only add a trailing space if its not the last polygon in the set */
 		}
 	}
 
 	/* Close outmost tag */
-	ptr += sprintf(ptr, "' /></IndexedFaceSet>");
-
-	return (ptr-output);
+	return stringbuffer_aprintf(sb, "' /></IndexedFaceSet>");
 }
 
 /*
- * Don't call this with single-geoms inspected!
+ * Computes X3D representation of TIN (as IndexedTriangleSet and adds to string buffer)
  */
-static char *
-asx3d3_psurface(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid)
+static int
+asx3d3_tin_sb(const LWTIN *tin, char *srs,  int precision, int opts, const char *defid, stringbuffer_t *sb)
 {
-	char *x3d;
-	size_t size;
-
-	size = asx3d3_psurface_size(psur, srs, precision, opts, defid);
-	x3d = lwalloc(size);
-	asx3d3_psurface_buf(psur, srs, x3d, precision, opts, defid);
-	return x3d;
-}
-
-
-static size_t
-asx3d3_tin_size(const LWTIN *tin, char *srs, int precision, int opts, const char *defid)
-{
 	int i;
-	size_t size;
-	size_t defidlen = strlen(defid);
-	/* int dimension=2; */
-
-	/** Need to make space for size of additional attributes,
-	** the coordIndex has a value for each edge for each triangle plus a space to separate so we need at least that much extra room ***/
-	size = sizeof("<IndexedTriangleSet coordIndex=''></IndexedTriangleSet>") + defidlen + tin->ngeoms*12;
-
-	for (i=0; i<tin->ngeoms; i++)
-	{
-		size += (asx3d3_triangle_size(tin->geoms[i], 0, precision, opts, defid) * 20); /** 3 is to make space for coordIndex **/
-	}
-
-	return size;
-}
-
-
-/*
- * Don't call this with single-geoms inspected!
- */
-static size_t
-asx3d3_tin_buf(const LWTIN *tin, char *srs, char *output, int precision, int opts, const char *defid)
-{
-	char *ptr;
-	int i;
 	int k;
 	/* int dimension=2; */
 
-	ptr = output;
-
-	ptr += sprintf(ptr, "<IndexedTriangleSet %s index='",defid);
+	stringbuffer_aprintf(sb,"<IndexedTriangleSet %s index='",defid);
 	k = 0;
 	/** Fill in triangle index **/
 	for (i=0; i<tin->ngeoms; i++)
 	{
-		ptr += sprintf(ptr, "%d %d %d", k, (k+1), (k+2));
+		stringbuffer_aprintf(sb, "%d %d %d", k, (k+1), (k+2));
 		if (i < (tin->ngeoms - 1) )
 		{
-			ptr += sprintf(ptr, " ");
+			stringbuffer_aprintf(sb, " ");
 		}
 		k += 3;
 	}
 
-	if ( X3D_USE_GEOCOORDS(opts) ) ptr += sprintf(ptr, "'><GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ( (opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
-	else ptr += sprintf(ptr, "'><Coordinate point='");
+	if ( X3D_USE_GEOCOORDS(opts) ) stringbuffer_aprintf(sb, "'><GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ( (opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
+	else stringbuffer_aprintf(sb, "'><Coordinate point='");
 
 	for (i=0; i<tin->ngeoms; i++)
 	{
-		ptr += asx3d3_triangle_buf(tin->geoms[i], 0, ptr, precision,
-		                           opts, defid);
+		asx3d3_triangle_sb(tin->geoms[i], 0, precision,
+		                           opts, defid, sb);
 		if (i < (tin->ngeoms - 1) )
 		{
-			ptr += sprintf(ptr, " ");
+			stringbuffer_aprintf(sb, " ");
 		}
 	}
 
 	/* Close outmost tag */
 
-	ptr += sprintf(ptr, "'/></IndexedTriangleSet>");
-
-	return (ptr-output);
+	return stringbuffer_aprintf(sb, "'/></IndexedTriangleSet>");
 }
 
-/*
- * Don't call this with single-geoms inspected!
- */
-static char *
-asx3d3_tin(const LWTIN *tin, char *srs, int precision, int opts, const char *defid)
+static int
+asx3d3_collection_sb(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
 {
-	char *x3d;
-	size_t size;
-
-	size = asx3d3_tin_size(tin, srs, precision, opts, defid);
-	x3d = lwalloc(size);
-	asx3d3_tin_buf(tin, srs, x3d, precision, opts, defid);
-	return x3d;
-}
-
-static size_t
-asx3d3_collection_size(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid)
-{
 	int i;
-	size_t size;
-	size_t defidlen = strlen(defid);
 	LWGEOM *subgeom;
 
-	/* size = sizeof("<MultiGeometry></MultiGeometry>") + defidlen*2; */
-	size = defidlen*2;
-
-	/** if ( srs )
-		size += strlen(srs) + sizeof(" srsName=.."); **/
-
-	for (i=0; i<col->ngeoms; i++)
-	{
-		subgeom = col->geoms[i];
-		size += ( sizeof("<Shape />") + defidlen ) * 2; /** for collections we need to wrap each in a shape tag to make valid **/
-		if ( subgeom->type == POINTTYPE )
-		{
-			size += asx3d3_point_size((LWPOINT*)subgeom, 0, precision, opts, defid);
-		}
-		else if ( subgeom->type == LINETYPE )
-		{
-			size += asx3d3_line_size((LWLINE*)subgeom, 0, precision, opts, defid);
-		}
-		else if ( subgeom->type == POLYGONTYPE )
-		{
-			size += asx3d3_poly_size((LWPOLY*)subgeom, 0, precision, opts, defid);
-		}
-		else if ( subgeom->type == TINTYPE )
-		{
-			size += asx3d3_tin_size((LWTIN*)subgeom, 0, precision, opts, defid);
-		}
-		else if ( subgeom->type == POLYHEDRALSURFACETYPE )
-		{
-			size += asx3d3_psurface_size((LWPSURFACE*)subgeom, 0, precision, opts, defid);
-		}
-		else if ( lwgeom_is_collection(subgeom) )
-		{
-			size += asx3d3_multi_size((LWCOLLECTION*)subgeom, 0, precision, opts, defid);
-		}
-		else
-			lwerror("asx3d3_collection_size: unknown geometry type");
-	}
-
-	return size;
-}
-
-static size_t
-asx3d3_collection_buf(const LWCOLLECTION *col, char *srs, char *output, int precision, int opts, const char *defid)
-{
-	char *ptr;
-	int i;
-	LWGEOM *subgeom;
-
-	ptr = output;
-
 	/* Open outmost tag */
-	/** @TODO: decide if we need outtermost tags, this one was just a copy from gml so is wrong **/
+	/** @TODO: if collection should be grouped, we'll wrap in a group tag.  Still needs cleanup
+	 * like the shapes should really be in a transform **/
 #ifdef PGIS_X3D_OUTERMOST_TAGS
-	if ( srs )
-	{
-		ptr += sprintf(ptr, "<%sMultiGeometry srsName=\"%s\">", defid, srs);
-	}
-	else
-	{
-		ptr += sprintf(ptr, "<%sMultiGeometry>", defid);
-	}
+	stringbuffer_aprintf(sb, "<%sGroup>", defid);
 #endif
 
 	for (i=0; i<col->ngeoms; i++)
 	{
 		subgeom = col->geoms[i];
-		ptr += sprintf(ptr, "<Shape%s>", defid);
+		stringbuffer_aprintf(sb, "<Shape%s>", defid);
 		if ( subgeom->type == POINTTYPE )
 		{
-			ptr += asx3d3_point_buf((LWPOINT*)subgeom, 0, ptr, precision, opts, defid);
+			asx3d3_point_sb((LWPOINT*)subgeom, 0, precision, opts, defid, sb);
 		}
 		else if ( subgeom->type == LINETYPE )
 		{
-			ptr += asx3d3_line_buf((LWLINE*)subgeom, 0, ptr, precision, opts, defid);
+			asx3d3_line_sb((LWLINE*)subgeom, 0, precision, opts, defid, sb);
 		}
 		else if ( subgeom->type == POLYGONTYPE )
 		{
-			ptr += asx3d3_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, opts, 0, defid);
+			asx3d3_poly_sb((LWPOLY*)subgeom, 0,  precision, opts, 0, defid, sb);
 		}
 		else if ( subgeom->type == TINTYPE )
 		{
-			ptr += asx3d3_tin_buf((LWTIN*)subgeom, srs, ptr, precision, opts,  defid);
+			asx3d3_tin_sb((LWTIN*)subgeom, srs,  precision, opts,  defid, sb);
 
 		}
 		else if ( subgeom->type == POLYHEDRALSURFACETYPE )
 		{
-			ptr += asx3d3_psurface_buf((LWPSURFACE*)subgeom, srs, ptr, precision, opts,  defid);
+			asx3d3_psurface_sb((LWPSURFACE*)subgeom, srs, precision, opts,  defid, sb);
 
 		}
 		else if ( lwgeom_is_collection(subgeom) )
 		{
 			if ( subgeom->type == COLLECTIONTYPE )
-				ptr += asx3d3_collection_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, opts, defid);
+				asx3d3_collection_sb((LWCOLLECTION*)subgeom, 0, precision, opts, defid, sb);
 			else
-				ptr += asx3d3_multi_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, opts, defid);
+				asx3d3_multi_sb((LWCOLLECTION*)subgeom, 0, precision, opts, defid, sb);
 		}
 		else
 			lwerror("asx3d3_collection_buf: unknown geometry type");
 
-		ptr += printf(ptr, "</Shape>");
+		stringbuffer_aprintf(sb, "</Shape>");
 	}
 
 	/* Close outmost tag */
 #ifdef PGIS_X3D_OUTERMOST_TAGS
-	ptr += sprintf(ptr, "</%sMultiGeometry>", defid);
+	stringbuffer_aprintf(sb,  "</%sGroup>", defid);
 #endif
 
-	return (ptr-output);
+	return LW_SUCCESS;
 }
 
-/*
- * Don't call this with single-geoms inspected!
- */
-static char *
-asx3d3_collection(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid)
-{
-	char *x3d;
-	size_t size;
-
-	size = asx3d3_collection_size(col, srs, precision, opts, defid);
-	x3d = lwalloc(size);
-	asx3d3_collection_buf(col, srs, x3d, precision, opts, defid);
-	return x3d;
-}
-
-
 /** In X3D3, coordinates are separated by a space separator
  */
-static size_t
-pointArray_toX3D3(POINTARRAY *pa, char *output, int precision, int opts, int is_closed)
+static int
+ptarray_to_x3d3_sb(POINTARRAY *pa, int precision, int opts, int is_closed, stringbuffer_t *sb )
 {
 	int i;
-	char *ptr;
 	char x[OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION+1];
 	char y[OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION+1];
 	char z[OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION+1];
 
-	ptr = output;
-
 	if ( ! FLAGS_GET_Z(pa->flags) )
 	{
 		for (i=0; i<pa->npoints; i++)
@@ -846,13 +524,12 @@
 					sprintf(y, "%g", pt.y);
 				trim_trailing_zeros(y);
 
-				if ( i )
-					ptr += sprintf(ptr, " ");
+				if ( i ) stringbuffer_append(sb," ");
 
 				if ( ( opts & LW_X3D_FLIP_XY) )
-					ptr += sprintf(ptr, "%s %s", y, x);
+					stringbuffer_aprintf(sb, "%s %s", y, x);
 				else
-					ptr += sprintf(ptr, "%s %s", x, y);
+					stringbuffer_aprintf(sb, "%s %s", x, y);
 			}
 		}
 	}
@@ -884,31 +561,15 @@
 					sprintf(z, "%g", pt.z);
 				trim_trailing_zeros(z);
 
-				if ( i )
-					ptr += sprintf(ptr, " ");
+				if ( i ) stringbuffer_append(sb," ");
 
 				if ( ( opts & LW_X3D_FLIP_XY) )
-					ptr += sprintf(ptr, "%s %s %s", y, x, z);
+					stringbuffer_aprintf(sb, "%s %s %s", y, x, z);
 				else
-					ptr += sprintf(ptr, "%s %s %s", x, y, z);
+					stringbuffer_aprintf(sb, "%s %s %s", x, y, z);
 			}
 		}
 	}
 
-	return ptr-output;
+	return LW_SUCCESS;
 }
-
-
-
-/**
- * Returns maximum size of rendered pointarray in bytes.
- */
-static size_t
-pointArray_X3Dsize(POINTARRAY *pa, int precision)
-{
-	if (FLAGS_NDIMS(pa->flags) == 2)
-		return (OUT_MAX_DIGS_DOUBLE + precision + sizeof(" "))
-		       * 2 * pa->npoints;
-
-	return (OUT_MAX_DIGS_DOUBLE + precision + sizeof(" ")) * 3 * pa->npoints;
-}

Modified: trunk/liblwgeom/lwout_x3d.h
===================================================================
--- trunk/liblwgeom/lwout_x3d.h	2018-01-05 23:43:58 UTC (rev 16223)
+++ trunk/liblwgeom/lwout_x3d.h	2018-01-08 17:09:09 UTC (rev 16224)
@@ -28,21 +28,19 @@
 **********************************************************************/
 #include <string.h>
 #include "liblwgeom_internal.h"
+#include "stringbuffer.h"
 
 /** defid is the id of the coordinate can be used to hold other elements DEF='abc' transform='' etc. **/
-static size_t asx3d3_point_size(const LWPOINT *point, char *srs, int precision, int opts, const char *defid);
-static char *asx3d3_point(const LWPOINT *point, char *srs, int precision, int opts, const char *defid);
-static size_t asx3d3_line_size(const LWLINE *line, char *srs, int precision, int opts, const char *defid);
-static char *asx3d3_line(const LWLINE *line, char *srs, int precision, int opts, const char *defid);
-static size_t asx3d3_poly_size(const LWPOLY *poly, char *srs, int precision, int opts, const char *defid);
-static size_t asx3d3_triangle_size(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid);
-static char *asx3d3_triangle(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid);
-static size_t asx3d3_multi_size(const LWCOLLECTION *col, char *srs, int precisioSn, int opts, const char *defid);
-static char *asx3d3_multi(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid);
-static char *asx3d3_psurface(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid);
-static char *asx3d3_tin(const LWTIN *tin, char *srs, int precision, int opts, const char *defid);
-static size_t asx3d3_collection_size(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid);
-static char *asx3d3_collection(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid);
-static size_t pointArray_toX3D3(POINTARRAY *pa, char *buf, int precision, int opts, int is_closed);
+static int lwgeom_to_x3d3_sb(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
 
-static size_t pointArray_X3Dsize(POINTARRAY *pa, int precision);
+static int asx3d3_point_sb(const LWPOINT *point, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int asx3d3_line_sb(const LWLINE *line, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+
+static int asx3d3_triangle_sb(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+
+static int asx3d3_multi_sb(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int asx3d3_psurface_sb(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int asx3d3_tin_sb(const LWTIN *tin, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+
+static int asx3d3_collection_sb(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
+static int ptarray_to_x3d3_sb(POINTARRAY *pa, int precision, int opts, int is_closed, stringbuffer_t *sb );



More information about the postgis-tickets mailing list