From 81b33875e407bdf4bb7ee69baf51c1ea7b6106b1 Mon Sep 17 00:00:00 2001 From: David Blasby <dblasby@gmail.com> Date: Tue, 4 Sep 2001 19:30:12 +0000 Subject: [PATCH] Added support to make WKB a full type. git-svn-id: http://svn.osgeo.org/postgis/trunk@60 b70326c6-7e19-0410-871a-916f4a2858ee --- postgis.h | 12 ++ postgis.sql.in | 17 ++- postgis_fn.c | 5 +- postgis_inout.c | 298 +++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 326 insertions(+), 6 deletions(-) diff --git a/postgis.h b/postgis.h index ca4f1347c..c65f5b470 100644 --- a/postgis.h +++ b/postgis.h @@ -205,6 +205,13 @@ typedef struct geomkey { } GEOMETRYKEY; +// WKB structure -- exactly the same as TEXT +typedef struct Well_known_bin { + int32 size; // total size of this structure + unsigned char data[1]; //THIS HOLD VARIABLE LENGTH DATA +} WellKnownBinary; + + //prototypes int isspace(int c); @@ -312,6 +319,8 @@ double distance_seg_seg(POINT3D *A, POINT3D *B, POINT3D *C, POINT3D *D); bool point_in_poly(POINT3D *p, POLYGON3D *poly); void print_point_debug(POINT3D *p); +unsigned char parse_hex(char *str); +void deparse_hex(unsigned char str, unsigned char *result); char *geometry_to_text(GEOMETRY *geometry); @@ -412,6 +421,9 @@ Datum centroid(PG_FUNCTION_ARGS); Datum postgis_gist_sel(PG_FUNCTION_ARGS); +Datum WKB_in(PG_FUNCTION_ARGS); +Datum WKB_out(PG_FUNCTION_ARGS); + //for GIST index typedef char* (*BINARY_UNION)(char*, char*, int*); diff --git a/postgis.sql.in b/postgis.sql.in index b7a1c9ef6..803a52950 100644 --- a/postgis.sql.in +++ b/postgis.sql.in @@ -241,11 +241,22 @@ CREATE TYPE BOX3D ( output = BOX3D_out ); +create function WKB_in(opaque) + RETURNS WKB + AS '@MODULE_FILENAME@','WKB_in' + LANGUAGE 'c' with (isstrict); + +create function WKB_out(opaque) + RETURNS opaque + AS '@MODULE_FILENAME@','WKB_out' + LANGUAGE 'c' with (isstrict); + + CREATE TYPE WKB ( - alignment = double, internallength = VARIABLE, - input = textin, - output = textout + input = WKB_in, + output = WKB_out, + storage= extended ); diff --git a/postgis_fn.c b/postgis_fn.c index fd4e1fa23..c0d226a10 100644 --- a/postgis_fn.c +++ b/postgis_fn.c @@ -2192,4 +2192,7 @@ Datum centroid(PG_FUNCTION_ARGS) pfree(cent); PG_RETURN_POINTER(result); -} \ No newline at end of file +} + + + diff --git a/postgis_inout.c b/postgis_inout.c index 3ca444078..2a27e9314 100644 --- a/postgis_inout.c +++ b/postgis_inout.c @@ -2764,7 +2764,7 @@ Datum asbinary_specify(PG_FUNCTION_ARGS) if ( ( strcmp(VARDATA(type) ,"xdr") == 0 ) || (strcmp(VARDATA(type) ,"XDR") == 0) ) { -printf("requested XDR\n"); +//printf("requested XDR\n"); if (BYTE_ORDER == BIG_ENDIAN) PG_RETURN_POINTER(to_wkb(geom, FALSE)); else @@ -2772,7 +2772,7 @@ printf("requested XDR\n"); } else { -printf("requested NDR\n"); +//printf("requested NDR\n"); if (BYTE_ORDER == LITTLE_ENDIAN) PG_RETURN_POINTER(to_wkb(geom, FALSE)); else @@ -3060,3 +3060,297 @@ LINE3D *make_line(int npoints, POINT3D *pts, int *size) return result; } +//given one byte, populate result with two byte representing +// the hex number +// ie deparse_hex( 255, mystr) +// -> mystr[0] = 'F' and mystr[1] = 'F' +// no error checking done +void deparse_hex(unsigned char str, unsigned char *result) +{ + int input_high; + int input_low; + + input_high = (str>>4); + input_low = (str & 0x0F); + + switch (input_high) + { + case 0: + result[0] = '0'; + break; + case 1: + result[0] = '1'; + break; + case 2: + result[0] = '2'; + break; + case 3: + result[0] = '3'; + break; + case 4: + result[0] = '4'; + break; + case 5: + result[0] = '5'; + break; + case 6: + result[0] = '6'; + break; + case 7: + result[0] = '7'; + break; + case 8: + result[0] = '8'; + break; + case 9: + result[0] = '9'; + break; + case 10: + result[0] = 'A'; + break; + case 11: + result[0] = 'B'; + break; + case 12: + result[0] = 'C'; + break; + case 13: + result[0] = 'D'; + break; + case 14: + result[0] = 'E'; + break; + case 15: + result[0] = 'F'; + break; + } + + switch (input_low) + { + case 0: + result[1] = '0'; + break; + case 1: + result[1] = '1'; + break; + case 2: + result[1] = '2'; + break; + case 3: + result[1] = '3'; + break; + case 4: + result[1] = '4'; + break; + case 5: + result[1] = '5'; + break; + case 6: + result[1] = '6'; + break; + case 7: + result[1] = '7'; + break; + case 8: + result[1] = '8'; + break; + case 9: + result[1] = '9'; + break; + case 10: + result[1] = 'A'; + break; + case 11: + result[1] = 'B'; + break; + case 12: + result[1] = 'C'; + break; + case 13: + result[1] = 'D'; + break; + case 14: + result[1] = 'E'; + break; + case 15: + result[1] = 'F'; + break; + } +} + + +//given a string with at least 2 chars in it, convert them to +// a byte value. No error checking done! +unsigned char parse_hex(char *str) +{ + //do this a little brute force to make it faster + + unsigned char result_high; + unsigned char result_low; + + switch (str[0]) + { + case '0' : + result_high = 0; + break; + case '1' : + result_high = 1; + break; + case '2' : + result_high = 2; + break; + case '3' : + result_high = 3; + break; + case '4' : + result_high = 4; + break; + case '5' : + result_high = 5; + break; + case '6' : + result_high = 6; + break; + case '7' : + result_high = 7; + break; + case '8' : + result_high = 8; + break; + case '9' : + result_high = 9; + break; + case 'A' : + result_high = 10; + break; + case 'B' : + result_high = 11; + break; + case 'C' : + result_high = 12; + break; + case 'D' : + result_high = 13; + break; + case 'E' : + result_high = 14; + break; + case 'F' : + result_high = 15; + break; + } + switch (str[1]) + { + case '0' : + result_low = 0; + break; + case '1' : + result_low = 1; + break; + case '2' : + result_low = 2; + break; + case '3' : + result_low = 3; + break; + case '4' : + result_low = 4; + break; + case '5' : + result_low = 5; + break; + case '6' : + result_low = 6; + break; + case '7' : + result_low = 7; + break; + case '8' : + result_low = 8; + break; + case '9' : + result_low = 9; + break; + case 'A' : + result_low = 10; + break; + case 'B' : + result_low = 11; + break; + case 'C' : + result_low = 12; + break; + case 'D' : + result_low = 13; + break; + case 'E' : + result_low = 14; + break; + case 'F' : + result_low = 15; + break; + } + return (unsigned char) ((result_high<<4) + result_low); +} + + +// input is a string with hex chars in it. Convert to binary and put in the result +PG_FUNCTION_INFO_V1(WKB_in); +Datum WKB_in(PG_FUNCTION_ARGS) +{ + char *str = PG_GETARG_CSTRING(0); + WellKnownBinary *result; + int size; + int t; + int input_str_len; + +//printf("wkb_in called\n"); + + input_str_len = strlen(str); + + if ( ( ( (int)(input_str_len/2.0) ) *2.0) != input_str_len) + { + elog(ERROR,"WKB_in parser - should be even number of characters!"); + PG_RETURN_NULL(); + } + + if (strspn(str,"0123456789ABCDEF") != strlen(str) ) + { + elog(ERROR,"WKB_in parser - input contains bad characters. Should only have '0123456789ABCDEF'!"); + PG_RETURN_NULL(); + } + size = (input_str_len/2) + 4; + result = (WellKnownBinary *) palloc(size); + result->size = size; + + for (t=0;t<input_str_len/2;t++) + { + ((unsigned char *)result)[t+4] = parse_hex( &str[t*2]) ; + } + PG_RETURN_POINTER(result); +} + + +//given a WKB structure, convert it to Hex and put it in a string +PG_FUNCTION_INFO_V1(WKB_out); +Datum WKB_out(PG_FUNCTION_ARGS) +{ + WellKnownBinary *WKB = (WellKnownBinary *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + char *result; + int size_result; + int t; + +//printf("wkb_out called\n"); + + size_result = (WKB->size - 4) *2 +1; //+1 for null char + result = palloc (size_result); + result[size_result-1] = 0; //null terminate + + for (t=0; t< (WKB->size -4); t++) + { + deparse_hex( ((unsigned char *) WKB)[4 + t], &result[t*2]); + } + PG_RETURN_CSTRING(result); +} + + -- 2.40.0