]> granicus.if.org Git - postgis/commitdiff
ZM aware WKT/WKB input/output.
authorSandro Santilli <strk@keybit.net>
Tue, 5 Oct 2004 07:53:02 +0000 (07:53 +0000)
committerSandro Santilli <strk@keybit.net>
Tue, 5 Oct 2004 07:53:02 +0000 (07:53 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@924 b70326c6-7e19-0410-871a-916f4a2858ee

lwgeom/liblwgeom.h
lwgeom/lwgparse.c
lwgeom/wktparse.lex
lwgeom/wktparse.y
lwgeom/wktunparse.c

index 9238f4cb21485e48627dc4fe0f18711ee57fe8f5..a689e6a444725d68ce94d3c451c621e48a9ed39c 100644 (file)
@@ -291,7 +291,7 @@ extern int pointArray_ptsize(const POINTARRAY *pa);
  *
  * LWGEOM types are an 8-bit char in this format:
  *
- * BSDDtttt
+ * BSZMtttt
  *
  * WHERE
  *    B = 16 byte BOX2DFLOAT4 follows (probably not aligned) [before SRID]
index 7382948e4b8f9818dcf577027164745467d6be93..b63cfb397200ca364a8fae32109a9f352a8adc5c 100644 (file)
@@ -72,6 +72,8 @@ struct {
        int     flags;
        int     srid;
        int     ndims;
+       int     hasZ;
+       int     hasM;
        /* create integer version */
        int lwgi;
        /* input is integer (wkb only)*/
@@ -149,7 +151,9 @@ byte* parse_it(const char* geometry,allocator allocfunc,report_error errfunc);
 byte* parse_lwg(const char* geometry,allocator allocfunc,report_error errfunc);
 byte* parse_lwgi(const char* geometry,allocator allocfunc,report_error errfunc);
 
-void set_srid(double d_srid){
+void
+set_srid(double d_srid)
+{
        if ( d_srid >= 0 )
                d_srid+=0.1;
        else
@@ -159,7 +163,9 @@ void set_srid(double d_srid){
        srid=(int)(d_srid+0.1);
 }
 
-tuple* alloc_tuple(output_func of,size_t size){
+tuple *
+alloc_tuple(output_func of,size_t size)
+{
        tuple* ret = free_list;
 
        if ( ! ret ){
@@ -195,12 +201,16 @@ tuple* alloc_tuple(output_func of,size_t size){
        return ret;
 }
 
-static void error(const char* err){
+static void
+error(const char* err)
+{
        error_func(err);
        ferror_occured=1;
 }
 
-void free_tuple(tuple* to_free){
+void
+free_tuple(tuple* to_free)
+{
 
        tuple* list_end = to_free;
 
@@ -215,14 +225,18 @@ void free_tuple(tuple* to_free){
        free_list = to_free;
 }
 
-void inc_num(void){
+void
+inc_num(void)
+{
        the_geom.stack->num++;
 }
 
 /*
        Allocate a 'counting' tuple
 */
-void alloc_stack_tuple(int type,output_func of,size_t size){
+void
+alloc_stack_tuple(int type,output_func of,size_t size)
+{
        tuple*  p;
        inc_num();
 
@@ -234,11 +248,15 @@ void alloc_stack_tuple(int type,output_func of,size_t size){
        the_geom.stack = p;
 }
 
-void pop(void){
+void
+pop(void)
+{
        the_geom.stack = the_geom.stack->stack_next;
 }
 
-void popc(void){
+void
+popc(void)
+{
        if ( the_geom.stack->num < minpoints){
                error("geometry requires more points");
        }
@@ -246,14 +264,16 @@ void popc(void){
 }
 
 
-void check_dims(int num){
-
+void
+check_dims(int num)
+{
        if( the_geom.ndims != num){
                if (the_geom.ndims) {
                        error("Can not mix dimentionality in a geometry");
-               }
-               else{
+               } else {
                        the_geom.ndims = num;
+                       if ( num > 2 ) the_geom.hasZ = 1;
+                       if ( num > 3 ) the_geom.hasM = 1;
                }
        }
 }
@@ -269,7 +289,9 @@ void check_dims(int num){
        machine
 */
 #ifdef SHRINK_INTS
-void WRITE_INT4(output_state * out,int4 val){
+void
+WRITE_INT4(output_state * out,int4 val)
+{
        if ( val <= 0x7f ){
                if ( getMachineEndian() == LITTLE_ENDIAN ){
                        val = (val<<1) | 1;
@@ -293,7 +315,9 @@ void WRITE_INT4(output_state * out,int4 val){
 #endif
 
 
-void WRITE_DOUBLES(output_state* out,double* points, int cnt){
+void
+WRITE_DOUBLES(output_state* out,double* points, int cnt)
+{
        if ( the_geom.lwgi){
                int4 vals[4];
                int i;
@@ -311,15 +335,21 @@ void WRITE_DOUBLES(output_state* out,double* points, int cnt){
 
 }
 
-void write_size(tuple* this,output_state* out){
+void
+write_size(tuple* this,output_state* out)
+{
        WRITE_INT4_REAL(out,the_geom.alloc_size);
 }
 
-void alloc_lwgeom(int srid){
+void
+alloc_lwgeom(int srid)
+{
        the_geom.srid=srid;
        the_geom.alloc_size=0;
        the_geom.stack=NULL;
        the_geom.ndims=0;
+       the_geom.hasZ=0;
+       the_geom.hasM=0;
 
        //Free if used already
        if ( the_geom.first ){
@@ -334,30 +364,45 @@ void alloc_lwgeom(int srid){
        the_geom.stack = alloc_tuple(write_size,4);
 }
 
-
-void write_point_2(tuple* this,output_state* out){
+void
+write_point_2(tuple* this,output_state* out)
+{
        WRITE_DOUBLES(out,this->points,2);
 }
 
-void write_point_3(tuple* this,output_state* out){
+void
+write_point_3(tuple* this,output_state* out)
+{
        WRITE_DOUBLES(out,this->points,3);
 }
-void write_point_4(tuple* this,output_state* out){
+
+void
+write_point_4(tuple* this,output_state* out)
+{
        WRITE_DOUBLES(out,this->points,4);
 }
 
-void write_point_2i(tuple* this,output_state* out){
+void
+write_point_2i(tuple* this,output_state* out)
+{
        WRITE_INT4_REAL_MULTIPLE(out,this->points,2);
 }
 
-void write_point_3i(tuple* this,output_state* out){
+void
+write_point_3i(tuple* this,output_state* out)
+{
        WRITE_INT4_REAL_MULTIPLE(out,this->points,3);
 }
-void write_point_4i(tuple* this,output_state* out){
+
+void
+write_point_4i(tuple* this,output_state* out)
+{
        WRITE_INT4_REAL_MULTIPLE(out,this->points,4);
 }
 
-void alloc_point_2d(double x,double y){
+void
+alloc_point_2d(double x,double y)
+{
        tuple* p = alloc_tuple(write_point_2,the_geom.lwgi?8:16);
        p->points[0] = x;
        p->points[1] = y;
@@ -365,7 +410,9 @@ void alloc_point_2d(double x,double y){
        check_dims(2);
 }
 
-void alloc_point_3d(double x,double y,double z){
+void
+alloc_point_3d(double x,double y,double z)
+{
        tuple* p = alloc_tuple(write_point_3,the_geom.lwgi?12:24);
        p->points[0] = x;
        p->points[1] = y;
@@ -374,7 +421,9 @@ void alloc_point_3d(double x,double y,double z){
        check_dims(3);
 }
 
-void alloc_point_4d(double x,double y,double z,double m){
+void
+alloc_point_4d(double x,double y,double z,double m)
+{
        tuple* p = alloc_tuple(write_point_4,the_geom.lwgi?16:32);
        p->points[0] = x;
        p->points[1] = y;
@@ -384,7 +433,9 @@ void alloc_point_4d(double x,double y,double z,double m){
        check_dims(4);
 }
 
-void write_type(tuple* this,output_state* out){
+void
+write_type(tuple* this,output_state* out)
+{
        byte type=0;
 
        //Empty handler - switch back
@@ -395,15 +446,7 @@ void write_type(tuple* this,output_state* out){
 
        if (the_geom.ndims) //Support empty
        {
-               if ( the_geom.ndims == 3 )
-               {
-                       TYPE_SETZM(type, 1, 0);
-               }
-               if ( the_geom.ndims == 4 )
-               {
-                       TYPE_SETZM(type, 1, 1);
-               }
-               //type |= ((the_geom.ndims-2) << 4);
+               TYPE_SETZM(type, the_geom.hasZ, the_geom.hasM);
        }
 
        if ( the_geom.srid != -1 ){
@@ -420,17 +463,23 @@ void write_type(tuple* this,output_state* out){
        }
 }
 
-void write_count(tuple* this,output_state* out){
+void
+write_count(tuple* this,output_state* out)
+{
        int num = this->num;
        WRITE_INT4(out,num);
 }
 
-void write_type_count(tuple* this,output_state* out){
+void
+write_type_count(tuple* this,output_state* out)
+{
        write_type(this,out);
        write_count(this,out);
 }
 
-void alloc_point(void){
+void
+alloc_point(void)
+{
        if( the_geom.lwgi)
                alloc_stack_tuple(POINTTYPEI,write_type,1);
        else
@@ -439,7 +488,9 @@ void alloc_point(void){
        minpoints=1;
 }
 
-void alloc_linestring(void){
+void
+alloc_linestring(void)
+{
        if( the_geom.lwgi)
                alloc_stack_tuple(LINETYPEI,write_type,1);
        else
@@ -448,7 +499,9 @@ void alloc_linestring(void){
        minpoints=2;
 }
 
-void alloc_polygon(void){
+void
+alloc_polygon(void)
+{
        if( the_geom.lwgi)
                alloc_stack_tuple(POLYGONTYPEI, write_type,1);
        else
@@ -457,27 +510,39 @@ void alloc_polygon(void){
        minpoints=3;
 }
 
-void alloc_multipoint(void){
+void
+alloc_multipoint(void)
+{
        alloc_stack_tuple(MULTIPOINTTYPE,write_type,1);
 }
 
-void alloc_multilinestring(void){
+void
+alloc_multilinestring(void)
+{
        alloc_stack_tuple(MULTILINETYPE,write_type,1);
 }
 
-void alloc_multipolygon(void){
+void
+alloc_multipolygon(void)
+{
        alloc_stack_tuple(MULTIPOLYGONTYPE,write_type,1);
 }
 
-void alloc_geomertycollection(void){
+void
+alloc_geomertycollection(void)
+{
        alloc_stack_tuple(COLLECTIONTYPE,write_type,1);
 }
 
-void alloc_counter(void){
+void
+alloc_counter(void)
+{
        alloc_stack_tuple(0,write_count,4);
 }
 
-void alloc_empty(){
+void
+alloc_empty()
+{
        tuple* st = the_geom.stack;
        //Find the last geometry
        while(st->type == 0){
@@ -504,7 +569,9 @@ void alloc_empty(){
 
 }
 
-byte* make_lwgeom(){
+byte *
+make_lwgeom()
+{
        byte* out_c;
        output_state out;
        tuple* cur;
@@ -524,7 +591,9 @@ byte* make_lwgeom(){
        return out_c;
 }
 
-int lwg_parse_yyerror(char* s){
+int
+lwg_parse_yyerror(char* s)
+{
        error("parse error - invalid geometry");
        //error_func("parse error - invalid geometry");
        return 1;
@@ -556,7 +625,9 @@ static const byte to_hex[]  = {
        255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
        255,255,255,255,255,255,255,255};
 
-byte strhex_readbyte(const char* in){
+byte
+strhex_readbyte(const char* in)
+{
        if ( *in == 0 ){
                if ( ! ferror_occured){
                        error("invalid wkb");
@@ -566,7 +637,9 @@ byte strhex_readbyte(const char* in){
        return to_hex[(int)*in]<<4 | to_hex[(int)*(in+1)];
 }
 
-byte read_wkb_byte(const char** in){
+byte
+read_wkb_byte(const char** in)
+{
        byte ret = strhex_readbyte(*in);
        (*in)+=2;
        return ret;
@@ -574,7 +647,9 @@ byte read_wkb_byte(const char** in){
 
 int swap_order;
 
-void read_wkb_bytes(const char** in,byte* out, int cnt){
+void
+read_wkb_bytes(const char** in,byte* out, int cnt)
+{
        if ( ! swap_order ){
                while(cnt--) *out++ = read_wkb_byte(in);
        }
@@ -584,13 +659,17 @@ void read_wkb_bytes(const char** in,byte* out, int cnt){
        }
 }
 
-int4 read_wkb_int(const char** in){
+int4
+read_wkb_int(const char** in)
+{
        int4 ret;
        read_wkb_bytes(in,(byte*)&ret,4);
        return ret;
 }
 
-double read_wbk_double(const char** in,int convert_from_int){
+double
+read_wbk_double(const char** in,int convert_from_int)
+{
        double ret;
 
        if ( ! convert_from_int){
@@ -603,7 +682,9 @@ double read_wbk_double(const char** in,int convert_from_int){
        }
 }
 
-void read_wkb_point(const char** b){
+void
+read_wkb_point(const char** b)
+{
        int i;
        tuple* p = NULL;
 
@@ -639,7 +720,9 @@ void read_wkb_point(const char** b){
        check_dims(the_geom.ndims);
 }
 
-void read_collection(const char** b,read_col_func f){
+void
+read_collection(const char** b,read_col_func f)
+{
        int4 cnt=read_wkb_int(b);
        alloc_counter();
 
@@ -651,11 +734,15 @@ void read_collection(const char** b,read_col_func f){
        pop();
 }
 
-void read_collection2(const char** b){
+void
+read_collection2(const char** b)
+{
        return read_collection(b,read_wkb_point);
 }
 
-void parse_wkb(const char** b){
+void
+parse_wkb(const char** b)
+{
        int4 type;
        byte xdr = read_wkb_byte(b);
        swap_order=0;
@@ -671,17 +758,22 @@ void parse_wkb(const char** b){
 
        type = read_wkb_int(b);
 
-
-
-
        //quick exit on error
        if ( ferror_occured ) return;
 
        the_geom.ndims=2;
        if (type & WKBZOFFSET)
-               the_geom.ndims=3;
+       {
+               the_geom.hasZ = 1;
+               the_geom.ndims++;
+       }
+       else the_geom.hasZ = 0;
        if (type & WKBMOFFSET)
-               the_geom.ndims=4;
+       {
+               the_geom.hasM = 1;
+               the_geom.ndims++;
+       }
+       else the_geom.hasM = 0;
 
        type &=0x0f;
 
@@ -746,14 +838,18 @@ void parse_wkb(const char** b){
 }
 
 
-void alloc_wkb(const char* parser){
+void
+alloc_wkb(const char* parser)
+{
        parse_wkb(&parser);
 }
 
 /*
        Parse a string and return a LW_GEOM
 */
-byte* parse_it(const char* geometry,allocator allocfunc,report_error errfunc){
+byte *
+parse_it(const char* geometry,allocator allocfunc,report_error errfunc)
+{
 
        local_malloc = allocfunc;
        error_func=errfunc;
@@ -770,15 +866,24 @@ byte* parse_it(const char* geometry,allocator allocfunc,report_error errfunc){
        return make_lwgeom();
 }
 
-byte* parse_lwg(const char* geometry,allocator allocfunc,report_error errfunc){
+byte *
+parse_lwg(const char* geometry,allocator allocfunc,report_error errfunc)
+{
        the_geom.lwgi=0;
        return parse_it(geometry,allocfunc,errfunc);
 }
 
-byte* parse_lwgi(const char* geometry,allocator allocfunc,report_error errfunc){
+byte *
+parse_lwgi(const char* geometry,allocator allocfunc,report_error errfunc)
+{
        the_geom.lwgi=1;
        return parse_it(geometry,allocfunc,errfunc);
 }
 
-
-
+void
+set_zm(char z, char m)
+{
+       the_geom.hasZ = z;
+       the_geom.hasM = m;
+       the_geom.ndims = 2+z+m;
+}
index ae694ac06bb37bac53cd3d73af52dbcd272bbcd5..e5ee602d657e9c94b427ad122a10691819342e95 100644 (file)
@@ -30,12 +30,19 @@ static YY_BUFFER_STATE buf_state;
 <INITIAL>01[0-9A-F]* {  lwg_parse_yylval.wkb=lwg_parse_yytext; return WKB;}
 
 <*>POINT       { return POINT; }
+<*>POINTM      { return POINTM; }
 <*>LINESTRING { return LINESTRING; }
+<*>LINESTRINGM { return LINESTRINGM; }
 <*>POLYGON { return POLYGON; }
+<*>POLYGONM { return POLYGONM; }
 <*>MULTIPOINT { return MULTIPOINT; }
+<*>MULTIPOINTM { return MULTIPOINTM; }
 <*>MULTILINESTRING { return MULTILINESTRING; }
+<*>MULTILINESTRINGM { return MULTILINESTRINGM; }
 <*>MULTIPOLYGON { return MULTIPOLYGON; }
+<*>MULTIPOLYGONM { return MULTIPOLYGONM; }
 <*>GEOMETRYCOLLECTION { return GEOMETRYCOLLECTION; }
+<*>GEOMETRYCOLLECTIONM { return GEOMETRYCOLLECTIONM; }
 <*>SRID { BEGIN(vals_ok); return SRID; }
 <*>EMPTY { return EMPTY; }
 
index eec4961a1d4e00216619007a0f2d0779da5d72bd..6cc24ccd634928a0b186fde65e5f1e3519784154 100644 (file)
@@ -19,6 +19,7 @@
 }
 
 %token POINT LINESTRING POLYGON MULTIPOINT MULTILINESTRING MULTIPOLYGON GEOMETRYCOLLECTION
+%token POINTM LINESTRINGM POLYGONM MULTIPOINTM MULTILINESTRINGM MULTIPOLYGONM GEOMETRYCOLLECTIONM
 %token SRID      
 %token EMPTY
 %token <value> VALUE
@@ -40,7 +41,7 @@ geom_wkb : WKB {alloc_wkb($1) ; } ;
 
 /* POINT */
 
-geom_point : POINT point ;
+geom_point : POINT point | POINTM { set_zm(0, 1); } point ;
 
 point : { alloc_point(); } point_int { pop();} ;
 
@@ -48,7 +49,8 @@ point_int : empty | LPAREN a_point RPAREN;
 
 /* MULTIPOINT */
 
-geom_multipoint : MULTIPOINT { alloc_multipoint(); } multipoint  { pop();};
+geom_multipoint : MULTIPOINT { alloc_multipoint(); } multipoint  { pop();} | 
+       MULTIPOINTM { set_zm(0, 1); alloc_multipoint(); } multipoint {pop();};
 
 multipoint : empty | { alloc_counter(); } LPAREN multipoint_int RPAREN {pop();} ;
 
@@ -59,7 +61,7 @@ mpoint : point  |  { alloc_point(); } a_point { pop();} ;
 
 /* LINESTRING */
 
-geom_linestring : LINESTRING linestring;
+geom_linestring : LINESTRING linestring | LINESTRINGM { set_zm(0, 1); } linestring ;
 
 linestring : { alloc_linestring(); } linestring_1 {pop();} ;
 
@@ -69,7 +71,7 @@ linestring_int : a_point | linestring_int COMMA a_point;
 
 /* MULTILINESTRING */
 
-geom_multilinestring : MULTILINESTRING { alloc_multilinestring(); } multilinestring  { pop();} ;
+geom_multilinestring : MULTILINESTRING { alloc_multilinestring(); } multilinestring  { pop();} | MULTILINESTRINGM { set_zm(0, 1); alloc_multilinestring(); } multilinestring { pop(); } ;
 
 multilinestring : empty | { alloc_counter(); } LPAREN multilinestring_int RPAREN{ pop();} ;
 
@@ -78,7 +80,7 @@ multilinestring_int : linestring | multilinestring_int COMMA linestring;
 
 /* POLYGON */
 
-geom_polygon : POLYGON polygon;
+geom_polygon : POLYGON polygon | POLYGONM { set_zm(0, 1); } polygon ;
 
 polygon : { alloc_polygon(); } polygon_1  { pop();} ;
 
@@ -88,7 +90,7 @@ polygon_int : linestring_1 | polygon_int COMMA linestring_1;
                                                                                                           
 /* MULTIPOLYGON */
 
-geom_multipolygon : MULTIPOLYGON { alloc_multipolygon(); } multipolygon   { pop();};
+geom_multipolygon : MULTIPOLYGON { alloc_multipolygon(); } multipolygon   { pop();} | MULTIPOLYGONM { set_zm(0, 1); alloc_multipolygon(); } multipolygon  { pop();} ;
 
 multipolygon : empty | { alloc_counter(); } LPAREN multipolygon_int RPAREN { pop();} ; 
 
@@ -98,7 +100,7 @@ multipolygon_int : polygon | multipolygon_int COMMA polygon;
 
 /* GEOMETRYCOLLECTION */
 
-geom_geometrycollection : GEOMETRYCOLLECTION { alloc_geomertycollection(); } geometrycollection { pop();} ;
+geom_geometrycollection : GEOMETRYCOLLECTION { alloc_geomertycollection(); } geometrycollection { pop();} | GEOMETRYCOLLECTIONM { set_zm(0, 1); alloc_geomertycollection(); } geometrycollection { pop();} ;
 
 geometrycollection : empty | { alloc_counter(); } LPAREN geometrycollection_int RPAREN { pop();} ;
 
index c1e4841e1a76aee4d2ec38ca1b6fca0869192a7e..7dc1d5f51b67f3e30fbd818a265c1a642cff53da 100644 (file)
@@ -167,14 +167,18 @@ byte* output_point(byte* geom,int supress){
        return geom;
 }
 
-byte* output_single(byte* geom,int supress){
+byte *
+output_single(byte* geom,int supress)
+{
        write_str("(");
        geom=output_point(geom,supress);
        write_str(")");
        return geom;
 }
 
-byte* output_collection(byte* geom,outfunc func,int supress){
+byte *
+output_collection(byte* geom,outfunc func,int supress)
+{
        int cnt = read_int(&geom);
        if ( cnt == 0 ){
                write_str(" EMPTY");
@@ -192,14 +196,16 @@ byte* output_collection(byte* geom,outfunc func,int supress){
        return geom;
 }
 
-byte* output_collection_2(byte* geom,int suppress){
+byte *
+output_collection_2(byte* geom,int suppress)
+{
        return output_collection(geom,output_point,suppress);
 }
 
-byteoutput_wkt(byte* geom, int supress);
+byte *output_wkt(byte* geom, int supress);
 
 /* special case for multipoint to supress extra brackets */
-byteoutput_multipoint(byte* geom,int suppress){
+byte *output_multipoint(byte* geom,int suppress){
        unsigned type = *geom & 0x0f;
        
        if ( type  == POINTTYPE )
@@ -214,70 +220,114 @@ byte* output_multipoint(byte* geom,int suppress){
        return output_wkt(geom,suppress);
 }
 
+// Suppress=0 // write TYPE, M, coords
+// Suppress=1 // write TYPE, coords 
+// Suppress=2 // write only coords
 byte *
 output_wkt(byte* geom, int supress)
 {
 
        unsigned type=*geom++;
        dims = TYPE_NDIMS(type); //((type & 0x30) >> 4)+2;
+       char writeM=0;
+
+       if ( ! supress && !TYPE_HASZ(type) && TYPE_HASM(type) ) writeM=1;
+
 
        //Skip the bounding box if there is one
-       //if ( type & 0x80 ){
        if ( TYPE_HASBBOX(type) )
        {
                geom+=16;
        }
 
-       //if ( type & 0x40 ){
        if ( TYPE_HASSRID(type) ) {
                write_str("SRID=");write_int(read_int(&geom));write_str(";");
        }
 
-       //switch(type & 0x0F){
        switch(TYPE_GETTYPE(type)) {
                case POINTTYPE:
-                       if ( ! supress) write_str("POINT");
+                       if ( supress < 2 )
+                       {
+                               if (writeM) write_str("POINTM");
+                               else write_str("POINT");
+                       }
                        geom=output_single(geom,0);
                        break;
                case LINETYPE:
-                       if ( ! supress) write_str("LINESTRING");
+                       if ( supress < 2 )
+                       {
+                               if (writeM) write_str("LINESTRINGM");
+                               else write_str("LINESTRING");
+                       }
                        geom = output_collection(geom,output_point,0);
                        break;
                case POLYGONTYPE:
-                       if ( ! supress) write_str("POLYGON");
+                       if ( supress < 2 )
+                       {
+                               if (writeM) write_str("POLYGONM");
+                               else write_str("POLYGON");
+                       }
                        geom = output_collection(geom,output_collection_2,0);
                        break;
                case MULTIPOINTTYPE:
-                       if ( ! supress) write_str("MULTIPOINT");
-                       geom = output_collection(geom,output_multipoint,1);
+                       if ( supress < 2 )
+                       {
+                               if (writeM) write_str("MULTIPOINTM");
+                               else write_str("MULTIPOINT");
+                       }
+                       geom = output_collection(geom,output_multipoint,2);
                        break;
                case MULTILINETYPE:
-                       if ( ! supress) write_str("MULTILINESTRING");
-                       geom = output_collection(geom,output_wkt,1);
+                       if ( supress < 2 )
+                       {
+                               if (writeM) write_str("MULTILINESTRINGM");
+                               else write_str("MULTILINESTRING");
+                       }
+                       geom = output_collection(geom,output_wkt,2);
                        break;
                case MULTIPOLYGONTYPE:
-                       if ( ! supress) write_str("MULTIPOLYGON");
-                       geom = output_collection(geom,output_wkt,1);
+                       if ( supress < 2 )
+                       {
+                               if (writeM) write_str("MULTIPOLYGONM");
+                               else write_str("MULTIPOLYGON");
+                       }
+                       geom = output_collection(geom,output_wkt,2);
                        break;
                case COLLECTIONTYPE:
-                       if ( ! supress) write_str("GEOMETRYCOLLECTION");
-                       geom = output_collection(geom,output_wkt,0);
+                       if ( supress < 2 )
+                       {
+                               if (writeM) write_str("GEOMETRYCOLLECTIONM");
+                               else write_str("GEOMETRYCOLLECTION");
+                       }
+                       geom = output_collection(geom,output_wkt,1);
                        break;
 
                case POINTTYPEI:
-                       if ( ! supress) write_str("POINT");
+                       if ( supress < 2 )
+                       {
+                               if (writeM) write_str("POINTM");
+                               else write_str("POINT");
+                       }
                        lwgi++;
                        geom=output_single(geom,0);
                        lwgi--;
                        break;
                case LINETYPEI:
-                       if ( ! supress) write_str("LINESTRING");
+                       if ( supress < 2 )
+                       {
+                               if (writeM) write_str("LINESTRINGM");
+                               else write_str("LINESTRING");
+                       }
                        lwgi++;
                        geom = output_collection(geom,output_point,0);
                        lwgi--;
                        break;
                case POLYGONTYPEI:
-                       if ( ! supress) write_str("POLYGON");
+                       if ( supress < 2 )
+                       {
+                               if (writeM) write_str("POLYGONM");
+                               else write_str("POLYGON");
+                       }
                        lwgi++;
                        geom =output_collection(geom,output_collection_2,0);
                        lwgi--;
@@ -429,7 +479,9 @@ output_wkb(byte* geom)
        return geom;
 }
 
-char* unparse_WKB(byte* lw_geom,allocator alloc,freeor free){
+char *
+unparse_WKB(byte* lw_geom,allocator alloc,freeor free)
+{
 
        if (lw_geom==NULL)
                return NULL;