cleanup
[hstore.git] / hstore_io.c
diff --git a/hstore_io.c b/hstore_io.c
deleted file mode 100644 (file)
index 089cb70..0000000
+++ /dev/null
@@ -1,372 +0,0 @@
-#include "hstore.h"
-#include <ctype.h>
-
-#ifdef PG_MODULE_MAGIC
-PG_MODULE_MAGIC;
-#endif
-
-typedef struct {
-       char *begin;
-       char *ptr;
-       char *cur;
-       char *word;
-       int wordlen;
-
-       Pairs   *pairs;
-       int     pcur;
-       int     plen;
-} HSParser;
-
-#define RESIZEPRSBUF \
-do { \
-        if ( state->cur - state->word + 1 >= state->wordlen ) \
-        { \
-                int4 clen = state->cur - state->word; \
-                state->wordlen *= 2; \
-                state->word = (char*)repalloc( (void*)state->word, state->wordlen ); \
-                state->cur = state->word + clen; \
-        } \
-} while (0)
-
-
-#define GV_WAITVAL 0 
-#define GV_INVAL 1 
-#define GV_INESCVAL 2 
-#define GV_WAITESCIN 3 
-#define GV_WAITESCESCIN 4 
-
-static bool
-get_val( HSParser *state, bool ignoreeq, bool *escaped ) {
-       int st = GV_WAITVAL;
-       state->wordlen=32;
-       state->cur = state->word = palloc( state->wordlen );
-       *escaped=false;
-
-       while(1) {
-               if ( st == GV_WAITVAL ) {
-                       if ( *(state->ptr) == '"' ) {
-                               *escaped=true;
-                               st = GV_INESCVAL;
-                       } else if ( *(state->ptr) == '\0' ) {
-                               return false;
-                       } else if (  *(state->ptr) == '=' && !ignoreeq ) {
-                               elog(ERROR,"Syntax error near '%c' at postion %d", *(state->ptr), state->ptr-state->begin);
-                       } else if ( *(state->ptr) == '\\' ) {
-                               st = GV_WAITESCIN;
-                       } else if ( !isspace(*(state->ptr)) ) {
-                               *(state->cur) = *(state->ptr);
-                               state->cur++;
-                               st = GV_INVAL;
-                       }
-               } else if ( st == GV_INVAL ) {
-                       if ( *(state->ptr) == '\\' ) {
-                               st = GV_WAITESCIN;
-                       } else if ( *(state->ptr) == '=' && !ignoreeq ) {
-                               state->ptr--;
-                               return true;
-                       } else if ( *(state->ptr) == ',' && ignoreeq ) {
-                               state->ptr--;
-                               return true;
-                       } else if ( isspace(*(state->ptr)) ) {
-                               return true;
-                       } else if ( *(state->ptr) == '\0' ) {
-                               state->ptr--;
-                               return true;
-                       } else {
-                               RESIZEPRSBUF;
-                               *(state->cur) = *(state->ptr);
-                               state->cur++;
-                       }
-               } else if ( st == GV_INESCVAL ) {
-                       if ( *(state->ptr) == '\\' ) {
-                               st = GV_WAITESCESCIN;
-                       } else if ( *(state->ptr) == '"' ) {
-                               return true;
-                       } else if ( *(state->ptr) == '\0' ) {
-                               elog(ERROR,"Unexpected end of string");
-                       } else {
-                               RESIZEPRSBUF;
-                               *(state->cur) = *(state->ptr);
-                               state->cur++;
-                       }
-               } else if ( st == GV_WAITESCIN ) {
-                       if ( *(state->ptr) == '\0' )
-                               elog(ERROR,"Unexpected end of string");
-                       RESIZEPRSBUF;
-                       *(state->cur) = *(state->ptr);
-                       state->cur++;
-                       st = GV_INVAL; 
-               } else if ( st == GV_WAITESCESCIN ) {
-                       if ( *(state->ptr) == '\0' )
-                               elog(ERROR,"Unexpected end of string");
-                       RESIZEPRSBUF;
-                       *(state->cur) = *(state->ptr);
-                       state->cur++;
-                       st = GV_INESCVAL;
-               } else
-                       elog(ERROR,"Unknown state %d at postion line %d in file '%s'", st, __LINE__, __FILE__); 
-
-               state->ptr++;
-       } 
-
-       return false;
-}
-
-#define WKEY   0
-#define WVAL   1
-#define WEQ    2
-#define WGT    3
-#define WDEL   4
-
-
-static void
-parse_hstore( HSParser *state ) {
-       int st = WKEY;
-       bool escaped=false;
-
-       state->plen=16;
-       state->pairs = (Pairs*)palloc( sizeof(Pairs) * state->plen );
-       state->pcur=0;
-       state->ptr = state->begin;
-       state->word=NULL;
-
-       while(1) {
-               if (st == WKEY) {
-                       if ( !get_val(state, false, &escaped) )
-                               return;
-                       if ( state->pcur >= state->plen ) {
-                               state->plen *= 2;
-                               state->pairs = (Pairs*)repalloc( state->pairs, sizeof(Pairs) * state->plen );
-                       }
-                       state->pairs[ state->pcur ].key = state->word; 
-                       state->pairs[ state->pcur ].keylen = state->cur - state->word;
-                       state->pairs[ state->pcur ].val=NULL;
-                       state->word=NULL;
-                       st = WEQ;
-               } else if ( st == WEQ ) {
-                       if ( *(state->ptr) == '=' ) {
-                               st = WGT;
-                       } else if ( *(state->ptr) == '\0' ) {
-                               elog(ERROR,"Unexpectd end of string");
-                       } else if (!isspace(*(state->ptr))) {
-                               elog(ERROR,"Syntax error near '%c' at postion %d", *(state->ptr), state->ptr-state->begin);
-                       }
-               } else if ( st == WGT ) {
-                       if ( *(state->ptr) == '>' ) {
-                               st = WVAL;
-                       } else if ( *(state->ptr) == '\0' ) {
-                               elog(ERROR,"Unexpectd end of string");
-                       } else { 
-                               elog(ERROR,"Syntax error near '%c' at postion %d", *(state->ptr), state->ptr-state->begin);
-                       }
-               } else if ( st == WVAL ) {
-                       if ( !get_val(state, true, &escaped) )
-                               elog(ERROR,"Unexpected end of string");
-                       state->pairs[ state->pcur ].val = state->word;
-                       state->pairs[ state->pcur ].vallen = state->cur - state->word;
-                       state->pairs[ state->pcur ].isnull = false;
-                       state->pairs[ state->pcur ].needfree = true;
-                       if ( state->cur - state->word == 4 && !escaped) {
-                               state->word[4] = '\0';
-                               if ( 0==strcasecmp(state->word, "null") ) 
-                                       state->pairs[ state->pcur ].isnull=true;
-                       } 
-                       state->word=NULL;
-                       state->pcur++;
-                       st = WDEL;
-               } else if ( st == WDEL ) {
-                       if (  *(state->ptr) == ',' ) {
-                               st = WKEY;
-                       } else if ( *(state->ptr) == '\0' ) {
-                               return;
-                       } else if (!isspace(*(state->ptr))) {
-                               elog(ERROR,"Syntax error near '%c' at postion %d", *(state->ptr), state->ptr-state->begin);
-                       }
-               } else 
-                       elog(ERROR,"Unknown state %d at line %d in file '%s'", st, __LINE__, __FILE__);
-
-               state->ptr++;
-       }
-} 
-
-int
-comparePairs(const void *a, const void *b) {
-       if ( ((Pairs*)a)->keylen == ((Pairs*)b)->keylen ) { 
-               int res =  strncmp(
-                               ((Pairs*)a)->key,
-                               ((Pairs*)b)->key,
-                               ((Pairs*)a)->keylen
-                       );
-               if ( res )
-                       return res;
-
-               /* guarantee that neddfree willl be later */
-               if ( ((Pairs*)b)->needfree == ((Pairs*)a)->needfree )
-                       return 0;
-               else if ( ((Pairs*)a)->needfree )
-                       return 1;
-               else
-                       return -1;  
-       }
-       return ( ((Pairs*)a)->keylen > ((Pairs*)b)->keylen ) ? 1 : -1;
-}
-
-int
-uniquePairs(Pairs * a, int4 l, int4 *buflen) {
-       Pairs *ptr, *res;
-
-       *buflen=0;
-       if ( l < 2 ) {
-               if ( l==1 )
-                       *buflen = a->keylen + ((a->isnull) ? 0 : a->vallen) ;
-               return l;
-       }
-
-       qsort((void *) a, l, sizeof(Pairs), comparePairs);
-       ptr=a+1;
-       res=a;  
-       while( ptr - a < l ) {
-               if ( ptr->keylen == res->keylen && strncmp( ptr->key, res->key, res->keylen )==0 ) {
-                       if ( ptr->needfree ) {
-                               pfree(ptr->key);
-                               pfree(ptr->val);
-                       }
-               } else {
-                       *buflen += res->keylen + (( res->isnull ) ? 0 : res->vallen);
-                       res++;
-                       memcpy(res,ptr,sizeof(Pairs));
-               }
-
-               ptr++;
-       }
-
-       *buflen += res->keylen + (( res->isnull ) ? 0 : res->vallen);
-       return res + 1 - a;
-}
-
-static void
-freeHSParse(HSParser *state) {
-       int i;
-
-       if ( state->word ) pfree( state->word );
-       for (i=0;i<state->pcur;i++)
-               if ( state->pairs[i].needfree ) {
-                       if (state->pairs[i].key) pfree(state->pairs[i].key);
-                       if (state->pairs[i].val) pfree(state->pairs[i].val);
-               }
-       pfree( state->pairs );
-}
-
-PG_FUNCTION_INFO_V1(hstore_in);
-Datum           hstore_in(PG_FUNCTION_ARGS);
-Datum
-hstore_in(PG_FUNCTION_ARGS) {
-       HSParser   state;
-       int4 len,buflen,i;
-       HStore  *out;
-       HEntry  *entries;
-       char *ptr;
-
-       state.begin =  PG_GETARG_CSTRING(0);
-
-       parse_hstore(&state);
-
-       if ( state.pcur == 0 ) {
-               freeHSParse(&state);
-               len = CALCDATASIZE(0,0);
-               out = palloc(len);
-               out->len=len;
-               out->size=0;
-               PG_RETURN_POINTER(out);
-       }
-
-       state.pcur = uniquePairs(state.pairs, state.pcur, &buflen);
-
-       len=CALCDATASIZE(state.pcur, buflen);
-       out = palloc(len);
-       out->len=len;
-       out->size=state.pcur;
-
-       entries=ARRPTR(out);
-       ptr = STRPTR(out);
-
-       for(i=0;i<out->size;i++) {
-               entries[i].keylen = state.pairs[i].keylen;
-               entries[i].pos = ptr - STRPTR(out);
-               memcpy(ptr, state.pairs[i].key, state.pairs[i].keylen);
-               ptr+=entries[i].keylen;
-
-               entries[i].valisnull = state.pairs[i].isnull;
-               if ( entries[i].valisnull )
-                       entries[i].vallen=4; /* null */
-               else {
-                       entries[i].vallen = state.pairs[i].vallen;
-                       memcpy(ptr, state.pairs[i].val,state.pairs[i].vallen);
-                       ptr+=entries[i].vallen;
-               }
-       }
-
-       freeHSParse(&state);
-       PG_RETURN_POINTER(out);
-}
-
-static char*
-cpw(char *dst, char *src, int len) {
-       char *ptr = src;
-
-       while(ptr-src<len) {
-               if ( *ptr == '"' || *ptr == '\\' )
-                       *dst++='\\';
-               *dst++ = *ptr++;
-       }
-       return dst;
-}
-
-PG_FUNCTION_INFO_V1(hstore_out);
-Datum           hstore_out(PG_FUNCTION_ARGS);
-Datum
-hstore_out(PG_FUNCTION_ARGS) {
-       HStore *in = PG_GETARG_HS(0);
-       int buflen,i;
-       char *out,*ptr;
-       char *base = STRPTR(in);
-       HEntry  *entries = ARRPTR(in);
-
-       if ( in->size==0 ) {
-               out=palloc(1);
-               *out='\0';
-               PG_FREE_IF_COPY(in,0);
-               PG_RETURN_CSTRING(out);
-       }
-
-       buflen = ( 4 /* " */ + 2 /* => */ + 2 /*, */ )*in->size + 
-               2 /* esc */ * ( in->len - CALCDATASIZE(in->size,0) );
-
-       out=ptr=palloc(buflen);
-       for(i=0;i<in->size;i++) {
-               *ptr++='"';
-               ptr = cpw( ptr, base + entries[i].pos, entries[i].keylen );
-               *ptr++='"';
-               *ptr++='=';
-               *ptr++='>';
-               if ( entries[i].valisnull ) {
-                       *ptr++='N';
-                       *ptr++='U';
-                       *ptr++='L';
-                       *ptr++='L';
-               } else {
-                       *ptr++='"';
-                       ptr = cpw( ptr, base + entries[i].pos + entries[i].keylen, entries[i].vallen );
-                       *ptr++='"';
-               }
-
-               if ( i+1 != in->size ) {
-                       *ptr++=',';
-                       *ptr++=' ';
-               }
-       }
-       *ptr='\0';
-
-       PG_FREE_IF_COPY(in,0);
-       PG_RETURN_CSTRING(out);
-}