]> granicus.if.org Git - postgis/commitdiff
#3177, gserialized_is_empty cannot handle nested empty cases
authorPaul Ramsey <pramsey@cleverelephant.ca>
Wed, 24 Jun 2015 22:40:57 +0000 (22:40 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Wed, 24 Jun 2015 22:40:57 +0000 (22:40 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@13700 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/cunit/cu_libgeom.c
liblwgeom/g_serialized.c

index 1d8e1fa5e1ee8a23e0bf5d495464ea8ea0991c70..99119f7f70307a9d37313b85385704175eef068b 100644 (file)
@@ -306,6 +306,49 @@ static void test_lwgeom_from_gserialized(void)
 
 }
 
+
+static void test_gserialized_is_empty(void)
+{
+       int i = 0;
+       struct gserialized_empty_cases {
+               const char* wkt;
+               int isempty;
+       };
+       
+       struct gserialized_empty_cases cases[] = {
+               { "POINT EMPTY", 1 },
+               { "POINT(1 1)", 0 },
+               { "LINESTRING EMPTY", 1 },
+               { "MULTILINESTRING EMPTY", 1 },
+               { "MULTILINESTRING(EMPTY)", 1 },
+               { "MULTILINESTRING(EMPTY,EMPTY)", 1 },
+               { "MULTILINESTRING(EMPTY,(0 0,1 1))", 0 },
+               { "MULTILINESTRING((0 0,1 1),EMPTY)", 0 },
+               { "MULTILINESTRING(EMPTY,(0 0,1 1),EMPTY)", 0 },
+               { "MULTILINESTRING(EMPTY,EMPTY,EMPTY)", 1 },
+               { "GEOMETRYCOLLECTION(POINT EMPTY,MULTILINESTRING(EMPTY,EMPTY,EMPTY))", 1 },
+               { "GEOMETRYCOLLECTION(POINT EMPTY,MULTILINESTRING(EMPTY),POINT(1 1))", 0 },
+               { "GEOMETRYCOLLECTION(POINT EMPTY,MULTILINESTRING(EMPTY, (0 0)),POINT EMPTY)", 0 },
+               { "GEOMETRYCOLLECTION(POLYGON EMPTY,POINT EMPTY,MULTILINESTRING(EMPTY,EMPTY),POINT EMPTY)", 1 },
+               { "GEOMETRYCOLLECTION(POLYGON EMPTY,GEOMETRYCOLLECTION(POINT EMPTY),MULTILINESTRING(EMPTY,EMPTY),POINT EMPTY)", 1 },
+               { NULL, 0 }
+       };
+       
+       while( cases[i].wkt )
+       {
+               // i = 11;
+               LWGEOM *lw = lwgeom_from_wkt(cases[i].wkt, LW_PARSER_CHECK_NONE);
+               GSERIALIZED *g = gserialized_from_lwgeom(lw, 0, 0);
+               int ie = gserialized_is_empty(g);
+               // printf("%s: we say %d, they say %d\n", cases[i].wkt, cases[i].isempty, ie);
+               CU_ASSERT_EQUAL(ie, cases[i].isempty);
+               lwgeom_free(lw);
+               lwfree(g);
+               i++;
+       }
+}
+       
+
 static void test_geometry_type_from_string(void)
 {
        int rv;
@@ -597,8 +640,8 @@ static void test_lwgeom_flip_coordinates(void)
 
 
        /*
-            * Srid
-            */
+       * Srid
+       */
 
        do_lwgeom_flip_coordinates(
            "SRID=4326;POINT(1 2)",
@@ -974,9 +1017,9 @@ static void test_lwgeom_scale(void)
 
        geom = lwgeom_from_wkt("SRID=4326;GEOMETRYCOLLECTION(POINT(0 1 2 3),POLYGON((-1 -1 0 1,-1 2.5 0 1,2 2 0 1,2 -1 0 1,-1 -1 0 1),(0 0 1 2,0 1 1 2,1 1 1 2,1 0 2 3,0 0 1 2)),LINESTRING(0 0 0 0, 1 2 3 4))", LW_PARSER_CHECK_NONE);
        factor.x = 2; factor.y = 3; factor.z = 4; factor.m = 5;
-  lwgeom_scale(geom, &factor);
+       lwgeom_scale(geom, &factor);
        out_ewkt = lwgeom_to_ewkt(geom);
-  ASSERT_STRING_EQUAL(out_ewkt, "SRID=4326;GEOMETRYCOLLECTION(POINT(0 3 8 15),POLYGON((-2 -3 0 5,-2 7.5 0 5,4 6 0 5,4 -3 0 5,-2 -3 0 5),(0 0 4 10,0 3 4 10,2 3 4 10,2 0 8 15,0 0 4 10)),LINESTRING(0 0 0 0,2 6 12 20))");
+       ASSERT_STRING_EQUAL(out_ewkt, "SRID=4326;GEOMETRYCOLLECTION(POINT(0 3 8 15),POLYGON((-2 -3 0 5,-2 7.5 0 5,4 6 0 5,4 -3 0 5,-2 -3 0 5),(0 0 4 10,0 3 4 10,2 3 4 10,2 0 8 15,0 0 4 10)),LINESTRING(0 0 0 0,2 6 12 20))");
        lwgeom_free(geom);
        lwfree(out_ewkt);
 
@@ -1024,4 +1067,5 @@ void libgeom_suite_setup(void)
        PG_ADD_TEST(suite, test_lwline_from_lwmpoint);
        PG_ADD_TEST(suite, test_lwgeom_as_curve);
        PG_ADD_TEST(suite, test_lwgeom_scale);
+       PG_ADD_TEST(suite, test_gserialized_is_empty);
 }
index 01bda61c44e72df0b35a2e07b3d6da0258de44c2..ced4177b2804f5b05be41a7c697a7dd4a0cf873f 100644 (file)
@@ -108,27 +108,46 @@ GSERIALIZED* gserialized_copy(const GSERIALIZED *g)
        return g_out;
 }
 
+static size_t gserialized_is_empty_recurse(const uint8_t *p, int *isempty);
+static size_t gserialized_is_empty_recurse(const uint8_t *p, int *isempty)
+{
+       int i;
+       int32_t type, num;
+
+       memcpy(&type, p, 4);
+       memcpy(&num, p+4, 4);
+       
+       if ( lwtype_is_collection(type) )
+       {
+               size_t lz = 8;
+               for ( i = 0; i < num; i++ )
+               {
+                       lz += gserialized_is_empty_recurse(p+lz, isempty);
+                       if ( ! *isempty )
+                               return lz;
+               }
+               *isempty = LW_TRUE;
+               return lz;
+       }
+       else
+       {
+               *isempty = (num == 0 ? LW_TRUE : LW_FALSE);
+               return 8;
+       }
+}
+
 int gserialized_is_empty(const GSERIALIZED *g)
 {
        uint8_t *p = (uint8_t*)g;
-       int i;
+       int isempty = 0;
        assert(g);
 
        p += 8; /* Skip varhdr and srid/flags */
        if( FLAGS_GET_BBOX(g->flags) )
                p += gbox_serialized_size(g->flags); /* Skip the box */
-       p += 4; /* Skip type number */
-       
-       /* For point/line/circstring this is npoints */
-       /* For polygons this is nrings */
-       /* For collections this is ngeoms */
-       memcpy(&i, p, sizeof(int));
-       
-       /* If it is non-zero, it's not empty */
-       if ( i > 0 )
-               return LW_FALSE;
-       else
-               return LW_TRUE; 
+
+       gserialized_is_empty_recurse(p, &isempty);
+       return isempty;
 }
 
 char* gserialized_to_string(const GSERIALIZED *g)