summaryrefslogtreecommitdiff
path: root/contrib/hstore/hstore_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/hstore/hstore_io.c')
-rw-r--r--contrib/hstore/hstore_io.c533
1 files changed, 318 insertions, 215 deletions
diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c
index 051a411a99..e01cb4e759 100644
--- a/contrib/hstore/hstore_io.c
+++ b/contrib/hstore/hstore_io.c
@@ -3,304 +3,396 @@
PG_MODULE_MAGIC;
-typedef struct {
- char *begin;
- char *ptr;
- char *cur;
- char *word;
- int wordlen;
-
- Pairs *pairs;
- int pcur;
- int plen;
-} HSParser;
+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; \
- } \
+ 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
+#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;
+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' ) {
+ }
+ else if (*(state->ptr) == '\0')
+ {
return false;
- } else if ( *(state->ptr) == '=' && !ignoreeq ) {
- elog(ERROR,"Syntax error near '%c' at postion %d", *(state->ptr), (int4)(state->ptr-state->begin));
- } else if ( *(state->ptr) == '\\' ) {
+ }
+ else if (*(state->ptr) == '=' && !ignoreeq)
+ {
+ elog(ERROR, "Syntax error near '%c' at postion %d", *(state->ptr), (int4) (state->ptr - state->begin));
+ }
+ else if (*(state->ptr) == '\\')
+ {
st = GV_WAITESCIN;
- } else if ( !isspace((unsigned char) *(state->ptr)) ) {
+ }
+ else if (!isspace((unsigned char) *(state->ptr)))
+ {
*(state->cur) = *(state->ptr);
state->cur++;
st = GV_INVAL;
}
- } else if ( st == GV_INVAL ) {
- if ( *(state->ptr) == '\\' ) {
+ }
+ else if (st == GV_INVAL)
+ {
+ if (*(state->ptr) == '\\')
+ {
st = GV_WAITESCIN;
- } else if ( *(state->ptr) == '=' && !ignoreeq ) {
+ }
+ else if (*(state->ptr) == '=' && !ignoreeq)
+ {
state->ptr--;
return true;
- } else if ( *(state->ptr) == ',' && ignoreeq ) {
+ }
+ else if (*(state->ptr) == ',' && ignoreeq)
+ {
state->ptr--;
return true;
- } else if ( isspace((unsigned char) *(state->ptr)) ) {
+ }
+ else if (isspace((unsigned char) *(state->ptr)))
+ {
return true;
- } else if ( *(state->ptr) == '\0' ) {
+ }
+ else if (*(state->ptr) == '\0')
+ {
state->ptr--;
return true;
- } else {
+ }
+ else
+ {
RESIZEPRSBUF;
*(state->cur) = *(state->ptr);
state->cur++;
}
- } else if ( st == GV_INESCVAL ) {
- if ( *(state->ptr) == '\\' ) {
+ }
+ else if (st == GV_INESCVAL)
+ {
+ if (*(state->ptr) == '\\')
+ {
st = GV_WAITESCESCIN;
- } else if ( *(state->ptr) == '"' ) {
+ }
+ else if (*(state->ptr) == '"')
+ {
return true;
- } else if ( *(state->ptr) == '\0' ) {
- elog(ERROR,"Unexpected end of string");
- } else {
+ }
+ 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");
+ }
+ 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");
+ 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__);
+ }
+ 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 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;
+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;
+ state->word = NULL;
- while(1) {
- if (st == WKEY) {
- if ( !get_val(state, false, &escaped) )
+ while (1)
+ {
+ if (st == WKEY)
+ {
+ if (!get_val(state, false, &escaped))
return;
- if ( state->pcur >= state->plen ) {
+ if (state->pcur >= state->plen)
+ {
state->plen *= 2;
- state->pairs = (Pairs*)repalloc( state->pairs, sizeof(Pairs) * state->plen );
+ 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;
+ 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) == '=' ) {
+ }
+ else if (st == WEQ)
+ {
+ if (*(state->ptr) == '=')
+ {
st = WGT;
- } else if ( *(state->ptr) == '\0' ) {
- elog(ERROR,"Unexpectd end of string");
- } else if (!isspace((unsigned char) *(state->ptr))) {
- elog(ERROR,"Syntax error near '%c' at postion %d", *(state->ptr), (int4)(state->ptr-state->begin));
}
- } else if ( st == WGT ) {
- if ( *(state->ptr) == '>' ) {
+ else if (*(state->ptr) == '\0')
+ {
+ elog(ERROR, "Unexpectd end of string");
+ }
+ else if (!isspace((unsigned char) *(state->ptr)))
+ {
+ elog(ERROR, "Syntax error near '%c' at postion %d", *(state->ptr), (int4) (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), (int4)(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) {
+ else if (*(state->ptr) == '\0')
+ {
+ elog(ERROR, "Unexpectd end of string");
+ }
+ else
+ {
+ elog(ERROR, "Syntax error near '%c' at postion %d", *(state->ptr), (int4) (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==pg_strcasecmp(state->word, "null") )
- state->pairs[ state->pcur ].isnull=true;
- }
- state->word=NULL;
+ if (0 == pg_strcasecmp(state->word, "null"))
+ state->pairs[state->pcur].isnull = true;
+ }
+ state->word = NULL;
state->pcur++;
st = WDEL;
- } else if ( st == WDEL ) {
- if ( *(state->ptr) == ',' ) {
+ }
+ else if (st == WDEL)
+ {
+ if (*(state->ptr) == ',')
+ {
st = WKEY;
- } else if ( *(state->ptr) == '\0' ) {
+ }
+ else if (*(state->ptr) == '\0')
+ {
return;
- } else if (!isspace((unsigned char) *(state->ptr))) {
- elog(ERROR,"Syntax error near '%c' at postion %d", *(state->ptr), (int4)(state->ptr-state->begin));
}
- } else
- elog(ERROR,"Unknown state %d at line %d in file '%s'", st, __LINE__, __FILE__);
+ else if (!isspace((unsigned char) *(state->ptr)))
+ {
+ elog(ERROR, "Syntax error near '%c' at postion %d", *(state->ptr), (int4) (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 )
+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 )
+ if (((Pairs *) b)->needfree == ((Pairs *) a)->needfree)
return 0;
- else if ( ((Pairs*)a)->needfree )
+ else if (((Pairs *) a)->needfree)
return 1;
else
- return -1;
+ return -1;
}
- return ( ((Pairs*)a)->keylen > ((Pairs*)b)->keylen ) ? 1 : -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) ;
+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 ) {
+ 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);
+ }
+ else
+ {
+ *buflen += res->keylen + ((res->isnull) ? 0 : res->vallen);
res++;
- memcpy(res,ptr,sizeof(Pairs));
+ memcpy(res, ptr, sizeof(Pairs));
}
ptr++;
}
- *buflen += res->keylen + (( res->isnull ) ? 0 : res->vallen);
+ *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);
+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 );
+ pfree(state->pairs);
}
PG_FUNCTION_INFO_V1(hstore_in);
-Datum hstore_in(PG_FUNCTION_ARGS);
+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);
+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 ) {
+ if (state.pcur == 0)
+ {
freeHSParse(&state);
- len = CALCDATASIZE(0,0);
+ len = CALCDATASIZE(0, 0);
out = palloc(len);
- out->len=len;
- out->size=0;
+ out->len = len;
+ out->size = 0;
PG_RETURN_POINTER(out);
}
state.pcur = uniquePairs(state.pairs, state.pcur, &buflen);
- len=CALCDATASIZE(state.pcur, buflen);
+ len = CALCDATASIZE(state.pcur, buflen);
out = palloc(len);
- out->len=len;
- out->size=state.pcur;
+ out->len = len;
+ out->size = state.pcur;
- entries=ARRPTR(out);
+ entries = ARRPTR(out);
ptr = STRPTR(out);
- for(i=0;i<out->size;i++) {
+ 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;
+ ptr += entries[i].keylen;
entries[i].valisnull = state.pairs[i].isnull;
- if ( entries[i].valisnull )
- entries[i].vallen=4; /* null */
- else {
+ 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;
+ memcpy(ptr, state.pairs[i].val, state.pairs[i].vallen);
+ ptr += entries[i].vallen;
}
}
@@ -308,63 +400,74 @@ hstore_in(PG_FUNCTION_ARGS) {
PG_RETURN_POINTER(out);
}
-static char*
-cpw(char *dst, char *src, int len) {
- char *ptr = src;
+static char *
+cpw(char *dst, char *src, int len)
+{
+ char *ptr = src;
- while(ptr-src<len) {
- if ( *ptr == '"' || *ptr == '\\' )
- *dst++='\\';
+ 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);
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);
+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++='"';
+ 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++=' ';
+ if (i + 1 != in->size)
+ {
+ *ptr++ = ',';
+ *ptr++ = ' ';
}
}
- *ptr='\0';
+ *ptr = '\0';
- PG_FREE_IF_COPY(in,0);
+ PG_FREE_IF_COPY(in, 0);
PG_RETURN_CSTRING(out);
}