]> granicus.if.org Git - postgis/commitdiff
Support parsing KML with space between digits and comma (#2372)
authorSandro Santilli <strk@keybit.net>
Fri, 28 Jun 2013 13:57:50 +0000 (13:57 +0000)
committerSandro Santilli <strk@keybit.net>
Fri, 28 Jun 2013 13:57:50 +0000 (13:57 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@11589 b70326c6-7e19-0410-871a-916f4a2858ee

postgis/lwgeom_in_kml.c
regress/in_kml.sql
regress/in_kml_expected

index bb3b78bd49d7c15f267a4b273238f53d901b1a69..d853ae8a9462e61a605a023cede4c50678e62914 100644 (file)
@@ -29,6 +29,8 @@
 
 #include <libxml/tree.h>
 #include <libxml/parser.h>
+#include <errno.h>
+#include <string.h>
 
 #include "postgres.h"
 
@@ -182,6 +184,7 @@ static xmlChar *kmlGetProp(xmlNodePtr xnode, xmlChar *prop)
 #endif
 
 
+#if 0 /* unused */
 /**
  * Parse a string supposed to be a double
  */
@@ -213,6 +216,8 @@ static double parse_kml_double(char *d, bool space_before, bool space_after)
        for (st = INIT, p = d ; *p ; p++)
        {
 
+lwnotice("State: %d, *p=%c", st, *p);
+
                if (isdigit(*p))
                {
                        if (st == INIT || st == NEED_DIG)       st = DIG;
@@ -253,6 +258,7 @@ static double parse_kml_double(char *d, bool space_before, bool space_after)
 
        return atof(d);
 }
+#endif /* unused */
 
 
 /**
@@ -261,11 +267,12 @@ static double parse_kml_double(char *d, bool space_before, bool space_after)
 static POINTARRAY* parse_kml_coordinates(xmlNodePtr xnode, bool *hasz)
 {
        xmlChar *kml_coord;
-       bool digit, found;
+       bool found;
        POINTARRAY *dpa;
        int kml_dims;
        char *p, *q;
        POINT4D pt;
+  double d;
 
        if (xnode == NULL) lwerror("invalid KML representation");
 
@@ -292,47 +299,44 @@ static POINTARRAY* parse_kml_coordinates(xmlNodePtr xnode, bool *hasz)
        /* HasZ, !HasM, 1pt */
        dpa = ptarray_construct_empty(1, 0, 1);
 
-       for (q = p, kml_dims=0, digit = false ; *p ; p++)
+  while (*p && isspace(*p)) ++p;
+       for (kml_dims=0; *p ; p++)
        {
+//lwnotice("*p:%c, kml_dims:%d", *p, kml_dims);
+    if ( isdigit(*p) || *p == '+' || *p == '-' || *p == '.' ) {
+                         kml_dims++;
+        errno = 0; d = strtod(p, &q);
+        if ( errno != 0 ) {
+          // TODO: destroy dpa, return NULL
+          lwerror("invalid KML representation"); /*: %s", strerror(errno));*/
+        }
+        if      (kml_dims == 1) pt.x = d;
+        else if (kml_dims == 2) pt.y = d;
+        else if (kml_dims == 3) pt.z = d;
+        else {
+          lwerror("invalid KML representation"); /* (more than 3 dimensions)"); */
+          // TODO: destroy dpa, return NULL
+        }
 
-               if (isdigit(*p)) digit = true;  /* One state parser */
-
-               /* Coordinate Separator */
-               if (*p == ',')
-               {
-                       *p = '\0';
-                       kml_dims++;
-
-                       if (*(p+1) == '\0') lwerror("invalid KML representation");
-
-                       if      (kml_dims == 1) pt.x = parse_kml_double(q, true, true);
-                       else if (kml_dims == 2) pt.y = parse_kml_double(q, true, true);
-                       q = p+1;
-
-                       /* Tuple Separator (or end string) */
-               }
-               else if (digit && (isspace(*p) || *(p+1) == '\0'))
-               {
-                       if (isspace(*p)) *p = '\0';
-                       kml_dims++;
-
-                       if (kml_dims < 2 || kml_dims > 3)
-                               lwerror("invalid KML representation");
-
-                       if (kml_dims == 3)
-                               pt.z = parse_kml_double(q, true, true);
-                       else
-                       {
-                               pt.y = parse_kml_double(q, true, true);
-                               *hasz = false;
-                       }
+//lwnotice("after strtod d:%f, *q:%c, kml_dims:%d", d, *q, kml_dims);
 
-                       ptarray_append_point(dpa, &pt, LW_FALSE);
-                       digit = false;
-                       q = p+1;
-                       kml_dims = 0;
+        if ( *q && ! isspace(*q) && *q != ',' ) {
+          lwerror("invalid KML representation"); /* (invalid character %c follows ordinate value)", *q); */
+        }
 
-               }
+        /* Look-ahead to see if we're done reading */
+        while (*q && isspace(*q)) ++q;
+        if ( isdigit(*q) || *q == '+' || *q == '-' || *q == '.' || ! *q ) {
+          if ( kml_dims < 2 ) lwerror("invalid KML representation"); /* (not enough ordinates)"); */
+          if ( kml_dims < 3 ) *hasz = false;
+          ptarray_append_point(dpa, &pt, LW_FALSE);
+          kml_dims = 0;
+        }
+        p = q-1; /* will be incrementedon next iteration */
+//lwnotice("after look-ahead *p:%c, kml_dims:%d", *p, kml_dims);
+    } else if ( *p != ',' && ! isspace(*p) ) {
+          lwerror("invalid KML representation"); /* (unexpected character %c)", *p); */
+    }
        }
 
        xmlFree(kml_coord);
index 599808a2d2e42ef65c32ddcfe3dde47c59a15a79..c02e7608880f21215b2032226600b05703ee6541 100644 (file)
@@ -37,11 +37,17 @@ SELECT 'xml_3', ST_AsEWKT(ST_GeomFromKML('<foo/>'));
 -- 1 Point
 SELECT 'point_1', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,2</kml:coordinates></kml:Point>'));
 
+-- See http://trac.osgeo.org/postgis/ticket/2372
+SELECT 'point_1a', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1 ,2</kml:coordinates></kml:Point>'));
+SELECT 'point_1b', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1, 2</kml:coordinates></kml:Point>'));
+SELECT 'point_1c', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates> 1,2</kml:coordinates></kml:Point>'));
+SELECT 'point_1d', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates> 1,2 </kml:coordinates></kml:Point>'));
+
 -- ERROR: 2 points
-SELECT 'point_2', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,2 3,4</kml:coordinates></kml:Point>'));
+SELECT 'point_error_1', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,2 3,4</kml:coordinates></kml:Point>'));
 
 -- ERROR: empty point
-SELECT 'point_3', ST_AsEWKT(ST_GeomFromKML('<kml:Point></kml:Point>'));
+SELECT 'point_error_2', ST_AsEWKT(ST_GeomFromKML('<kml:Point></kml:Point>'));
 
 
 
index f1670b7acc2e64879338b167b6317255156a3ee2..063b9ea6d05813ffcc0f06eff1f387c429e7017a 100644 (file)
@@ -3,6 +3,10 @@ ERROR:  invalid KML representation
 ERROR:  invalid KML representation
 ERROR:  invalid KML representation
 point_1|SRID=4326;POINT(1 2)
+point_1a|SRID=4326;POINT(1 2)
+point_1b|SRID=4326;POINT(1 2)
+point_1c|SRID=4326;POINT(1 2)
+point_1d|SRID=4326;POINT(1 2)
 ERROR:  invalid KML representation
 ERROR:  invalid KML representation
 linestring_1|SRID=4326;LINESTRING(1 2,3 4)
@@ -47,7 +51,7 @@ ERROR:  invalid KML representation
 ERROR:  invalid KML representation
 coordinates_12|SRID=4326;LINESTRING(1 2,3 4)
 coordinates_13|SRID=4326;LINESTRING(1 2,3 4)
-ERROR:  invalid KML representation
+coordinates_14|SRID=4326;LINESTRING(1 2,3 4)
 coordinates_15|SRID=4326;LINESTRING(1 2,3 4)
 coordinates_16|SRID=4326;LINESTRING(1 2,3 4)
 ERROR:  invalid KML representation
@@ -72,8 +76,8 @@ double_6|SRID=4326;POINT(1 1.2)
 double_7|SRID=4326;POINT(1 1.23)
 double_8|SRID=4326;POINT(1 1)
 ERROR:  invalid KML representation
-ERROR:  invalid KML representation
-ERROR:  invalid KML representation
+double_10|SRID=4326;POINT(1 0.1)
+double_11|SRID=4326;POINT(1 -0.1)
 ERROR:  invalid KML representation
 ERROR:  invalid KML representation
 ERROR:  invalid KML representation