From 98df5600a66b599f571a34bce7b5f1cbd12f53c6 Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Mon, 11 Oct 2004 14:03:33 +0000 Subject: [PATCH] Added endiannes specification to unparse_WKB, AsBinary, lwgeom_to_wkb. git-svn-id: http://svn.osgeo.org/postgis/trunk@984 b70326c6-7e19-0410-871a-916f4a2858ee --- lwgeom/liblwgeom.h | 3 +- lwgeom/lwgeom.c | 12 +++++++ lwgeom/lwgeom.h | 1 + lwgeom/lwgeom_inout.c | 27 ++++++++++++-- lwgeom/lwgeom_ogc.c | 4 --- lwgeom/lwgeom_pg.h | 4 +++ lwgeom/lwpostgis.sql.in | 5 +++ lwgeom/test.c | 6 ++-- lwgeom/wktparse.h | 2 +- lwgeom/wktunparse.c | 79 +++++++++++++++++++++++++++++------------ 10 files changed, 111 insertions(+), 32 deletions(-) diff --git a/lwgeom/liblwgeom.h b/lwgeom/liblwgeom.h index 17b6a99fd..0a33ee106 100644 --- a/lwgeom/liblwgeom.h +++ b/lwgeom/liblwgeom.h @@ -1007,7 +1007,8 @@ extern LWCOLLECTION *lwcollection_segmentize2d(LWCOLLECTION *coll, double dist); extern unsigned char parse_hex(char *str); extern void deparse_hex(unsigned char str, unsigned char *result); extern char *parse_lwgeom_wkt(char *wkt_input); -extern char * lwgeom_to_wkt(LWGEOM *lwgeom); +extern char *lwgeom_to_wkt(LWGEOM *lwgeom); +extern char *lwgeom_to_hexwkb(LWGEOM *lwgeom, unsigned int byteorder); extern void *lwalloc(size_t size); extern void *lwrealloc(void *mem, size_t size); diff --git a/lwgeom/lwgeom.c b/lwgeom/lwgeom.c index 408262d6f..ad2b4c994 100644 --- a/lwgeom/lwgeom.c +++ b/lwgeom/lwgeom.c @@ -371,6 +371,18 @@ lwgeom_to_wkt(LWGEOM *lwgeom) return ret; } +/* + * Return an alloced string + */ +char * +lwgeom_to_hexwkb(LWGEOM *lwgeom, unsigned int byteorder) +{ + char *serialized = lwgeom_serialize(lwgeom); + char *hexwkb = unparse_WKB(serialized, lwalloc, lwfree, byteorder); + lwfree(serialized); + return hexwkb; +} + // geom1 same as geom2 // iff // + have same type // + have same # objects diff --git a/lwgeom/lwgeom.h b/lwgeom/lwgeom.h index cc2b62b03..9c475a547 100644 --- a/lwgeom/lwgeom.h +++ b/lwgeom/lwgeom.h @@ -31,6 +31,7 @@ typedef struct LWGEOM_T *LWGEOM; // Conversions extern char *lwgeom_to_wkt(LWGEOM lwgeom); +extern char *lwgeom_to_hexwkb(LWGEOM lwgeom, unsigned int byteorder); // Construction extern LWGEOM lwpoint_construct(int SRID, char wantbbox, POINTARRAY pa); diff --git a/lwgeom/lwgeom_inout.c b/lwgeom/lwgeom_inout.c index 05ab4c441..653bb6977 100644 --- a/lwgeom/lwgeom_inout.c +++ b/lwgeom/lwgeom_inout.c @@ -117,7 +117,7 @@ Datum LWGEOM_out(PG_FUNCTION_ARGS) init_pg_func(); lwgeom = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - result = unparse_WKB(SERIALIZED_FORM(lwgeom),lwalloc,lwfree); + result = unparse_WKB(SERIALIZED_FORM(lwgeom),lwalloc,lwfree,-1); PG_RETURN_CSTRING(result); } @@ -201,11 +201,34 @@ Datum WKBFromLWGEOM(PG_FUNCTION_ARGS) int size_result; char *semicolonLoc; int t; + text *type; + unsigned int byteorder=-1; init_pg_func(); + if ( (PG_NARGS()>1) && (!PG_ARGISNULL(1)) ) + { + type = PG_GETARG_TEXT_P(1); + if (VARSIZE(type) < 7) + { + elog(ERROR,"asbinary(geometry, ) - type should be 'XDR' or 'NDR'. type length is %i",VARSIZE(type) -4); + PG_RETURN_NULL(); + } + + if ( ! strncmp(VARDATA(type), "xdr", 3) || + ! strncmp(VARDATA(type), "XDR", 3) ) + { + byteorder = BIG_ENDIAN; + } + else + { + byteorder = LITTLE_ENDIAN; + } + } + lwgeom_input = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - hexized_wkb_srid = unparse_WKB(SERIALIZED_FORM(lwgeom_input), lwalloc, lwfree); + hexized_wkb_srid = unparse_WKB(SERIALIZED_FORM(lwgeom_input), + lwalloc, lwfree, byteorder); //elog(NOTICE, "in WKBFromLWGEOM with WKB = '%s'", hexized_wkb_srid); diff --git a/lwgeom/lwgeom_ogc.c b/lwgeom/lwgeom_ogc.c index 5c186f638..984badb00 100644 --- a/lwgeom/lwgeom_ogc.c +++ b/lwgeom/lwgeom_ogc.c @@ -709,11 +709,7 @@ Datum LWGEOM_from_text(PG_FUNCTION_ARGS) PG_LWGEOM *result = NULL; // read user-requested SRID if any -#if USE_VERSION < 73 - if ( fcinfo->nargs > 1 ) -#else if ( PG_NARGS() > 1 ) -#endif { SRID = PG_GETARG_INT32(1); if ( SRID != lwgeom_getSRID(geom) ) diff --git a/lwgeom/lwgeom_pg.h b/lwgeom/lwgeom_pg.h index f09a24382..35f6d2ff9 100644 --- a/lwgeom/lwgeom_pg.h +++ b/lwgeom/lwgeom_pg.h @@ -6,6 +6,10 @@ #include "fmgr.h" #include "liblwgeom.h" +#ifndef PG_NARGS +#define PG_NARGS() (fcinfo->nargs) +#endif + void *pg_alloc(size_t size); void *pg_realloc(void *ptr, size_t size); void pg_free(void *ptr); diff --git a/lwgeom/lwpostgis.sql.in b/lwgeom/lwpostgis.sql.in index 981d64916..75eb6bc0b 100644 --- a/lwgeom/lwpostgis.sql.in +++ b/lwgeom/lwpostgis.sql.in @@ -1077,6 +1077,11 @@ CREATEFUNCTION AsBinary(geometry) AS '@MODULE_FILENAME@','WKBFromLWGEOM' LANGUAGE 'C' WITH (isstrict,iscachable); +CREATEFUNCTION AsBinary(geometry,text) + RETURNS bytea + AS '@MODULE_FILENAME@','WKBFromLWGEOM' + LANGUAGE 'C' WITH (isstrict,iscachable); + CREATEFUNCTION AsText(geometry) RETURNS TEXT AS '@MODULE_FILENAME@','LWGEOM_asText' diff --git a/lwgeom/test.c b/lwgeom/test.c index ddb951b0a..78cfc7e18 100644 --- a/lwgeom/test.c +++ b/lwgeom/test.c @@ -26,8 +26,9 @@ int main() // Construct a point LWGEOM point = lwpoint_construct(-1, 0, pa); - // Print WKT + // Print WKT end HEXWKB printf("WKT: %s\n", lwgeom_to_wkt(point)); + printf("HEXWKB: %s\n", lwgeom_to_hexwkb(point,-1)); // Construct a 5-points pointarray2d pa = ptarray_construct2d(5, pts2d); @@ -35,8 +36,9 @@ int main() // Construct a line LWGEOM line = lwline_construct(-1, 0, pa); - // Print WKT + // Print WKT and HEXWKB printf("WKT: %s\n", lwgeom_to_wkt(line)); + printf("HEXWKB: %s\n", lwgeom_to_hexwkb(point,-1)); return 1; } diff --git a/lwgeom/wktparse.h b/lwgeom/wktparse.h index a0fb5136f..f975845d8 100644 --- a/lwgeom/wktparse.h +++ b/lwgeom/wktparse.h @@ -68,6 +68,6 @@ void alloc_wkb(const char* parser); byte* parse_lwg(const char* wkt,allocator allocfunc,report_error errfunc); byte* parse_lwgi(const char* wkt,allocator allocfunc,report_error errfunc); char* unparse_WKT(byte* serialized, allocator alloc,freeor free); -char* unparse_WKB(byte* serialized, allocator alloc,freeor free); +char* unparse_WKB(byte* serialized, allocator alloc,freeor free, unsigned int endian); diff --git a/lwgeom/wktunparse.c b/lwgeom/wktunparse.c index 92bc6acbe..d4cc1634d 100644 --- a/lwgeom/wktunparse.c +++ b/lwgeom/wktunparse.c @@ -4,8 +4,10 @@ * Copyright Telogis 2004 * www.telogis.com * + * $Id$ */ + #include "wktparse.h" #include #include @@ -21,9 +23,17 @@ static int endian_check_int = 1; // dont modify this!!! #define LITTLE_ENDIAN_CHECK 1 -static char getMachineEndian() +static unsigned int getMachineEndian() { - return *((char *) &endian_check_int); // 0 = big endian, 1 = little endian + // 0 = big endian, 1 = little endian + if ( *((char *) &endian_check_int) ) + { + return LITTLE_ENDIAN; + } + else + { + return BIG_ENDIAN; + } } //-- Typedefs ---------------------------------------------- @@ -46,7 +56,7 @@ byte* output_single(byte* geom,int supress); byte* output_collection(byte* geom,outfunc func,int supress); byte* output_collection_2(byte* geom,int suppress); byte* output_multipoint(byte* geom,int suppress); -void write_wkb_bytes(byte* ptr,int cnt); +void write_wkb_bytes(byte* ptr,unsigned int cnt,size_t size); void write_wkb_int(int i); byte* output_wkb_collection(byte* geom,outwkbfunc func); byte* output_wkb_collection_2(byte* geom); @@ -62,6 +72,7 @@ static char* out_start; static char* out_pos; static int len; static int lwgi; +static int flipbytes; //---------------------------------------------------------- @@ -368,13 +379,30 @@ unparse_WKT(byte* serialized, allocator alloc, freeor free) static char outchr[]={"0123456789ABCDEF" }; void -write_wkb_bytes(byte* ptr,int cnt){ - ensure(cnt*2); +write_wkb_bytes(byte* ptr, unsigned int cnt, size_t size) +{ + unsigned int bc; // byte count + + ensure(cnt*2*size); while(cnt--){ - *out_pos++ = outchr[*ptr>>4]; - *out_pos++ = outchr[*ptr&0x0F]; - ptr ++; + if (flipbytes) + { + for(bc=size; bc; bc--) + { + *out_pos++ = outchr[ptr[bc-1]>>4]; + *out_pos++ = outchr[ptr[bc-1]&0x0F]; + } + } + else + { + for(bc=0; bc>4]; + *out_pos++ = outchr[ptr[bc]&0x0F]; + } + } + ptr+=size; } } @@ -382,18 +410,18 @@ byte * output_wkb_point(byte* geom) { if ( lwgi ){ - write_wkb_bytes(geom,dims*4); + write_wkb_bytes(geom,dims,4); return geom + (4*dims); } else{ - write_wkb_bytes(geom,dims*8); + write_wkb_bytes(geom,dims,8); return geom + (8*dims); } } void write_wkb_int(int i){ - write_wkb_bytes((byte*)&i,4); + write_wkb_bytes((byte*)&i,1,4); } byte * @@ -419,7 +447,6 @@ output_wkb(byte* geom) { unsigned char type=*geom++; int4 wkbtype; - byte endian; dims = TYPE_NDIMS(type); #ifdef DEBUG @@ -445,15 +472,6 @@ output_wkb(byte* geom) if ( TYPE_HASM(type) ) wkbtype |= WKBMOFFSET; - if ( getMachineEndian() != LITTLE_ENDIAN_CHECK ){ - endian=0; - write_wkb_bytes(&endian,1); - } - else{ - endian=1; - write_wkb_bytes(&endian,1); - } - write_wkb_int(wkbtype); switch(TYPE_GETTYPE(type)){ @@ -501,8 +519,9 @@ output_wkb(byte* geom) } char * -unparse_WKB(byte* serialized, allocator alloc, freeor free) +unparse_WKB(byte* serialized, allocator alloc, freeor free, unsigned int endian) { + byte endianbyte; #ifdef DEBUG lwnotice("unparse_WKB(%p,...) called", serialized); @@ -517,6 +536,16 @@ unparse_WKB(byte* serialized, allocator alloc, freeor free) out_start = out_pos = alloc(len); lwgi=0; + if ( endian == -1 ) endian = getMachineEndian(); + + if ( endian == LITTLE_ENDIAN) endianbyte=1; + else endianbyte=0; + + write_wkb_bytes(&endianbyte,1,1); + + if ( endian != getMachineEndian() ) flipbytes = 1; + else flipbytes = 0; + output_wkb(serialized); ensure(1); *out_pos=0; @@ -525,3 +554,9 @@ unparse_WKB(byte* serialized, allocator alloc, freeor free) } +/****************************************************************** + * $Log$ + * Revision 1.10 2004/10/11 14:03:33 strk + * Added endiannes specification to unparse_WKB, AsBinary, lwgeom_to_wkb. + * + ******************************************************************/ -- 2.49.0