Implement simple query_string parser
[tedtools.git] / prs_hmap.c
index 76e0769..ad79ffe 100644 (file)
@@ -148,3 +148,126 @@ parse_hmap(char *in, HMap ** m) {
        else if (!(state == CS_WAITDELIM || state == CS_WAITKEY))
                tlog(TL_ALARM|TL_EXIT,"parse_hmap: unexpected end of line\n");
 }
+
+static int 
+getnumber(char c)  {
+       if ( c == '\0' )
+               return 0;
+       else if ( c >= '0' && c <= '9' )
+               return c - '0';
+       else if ( c >= 'A' && c <= 'F' )
+               return c - 'A' + 10;
+       else if ( c >= 'a' && c <= 'f' )
+               return c - 'a' + 10;
+
+       return -1;
+}
+
+static char * 
+unescape(char *str, int len) {
+       char *in = str, *out = tmalloc(sizeof(char)*(len+1));
+       char *res = out; 
+
+       while(in - str < len )  {
+               char c = *in;
+
+               if ( c == '+' ) 
+                       c = ' ';
+               else if ( c == '%' ) {
+                       char *ptr = in;
+                       int  i1, i2;
+
+                       ptr++;
+                       if ( ptr - str >= len || (i1=getnumber(*ptr)) < 0 ) 
+                               goto process;
+                       ptr++;
+                       if ( ptr - str >= len || (i2=getnumber(*ptr)) < 0 ) 
+                               goto process;
+
+                       c = (i1<<4) | i2;
+
+                       in+=2;
+               }
+
+process:
+               *out = c;
+               out++; in++;
+       }
+
+       *out = '\0';
+
+       return res;
+}
+
+#define QS_WAITKEY     1
+#define QS_INKEY       2
+#define QS_WAITVAL     3
+#define QS_INVAL       4
+
+int   
+parse_query_string(char *in, HMap ** m) {
+       HMap            *mptr;
+       char            *ptr = in,
+                               *begin = NULL;
+       char            num = 0;
+       int                     state = QS_WAITKEY;
+
+       while (*ptr)
+       {
+               if (*ptr == '&')
+                       num++;
+               ptr++;
+       }
+
+       *m = mptr = (HMap *) t0malloc(sizeof(HMap) * (num + 2));
+       ptr = in;
+       while (*ptr) {
+               if ( state == QS_WAITKEY ) {
+                       if ( !( *ptr == '&'  || *ptr == '=' ) ) {
+                               begin = ptr;
+                               state = QS_INKEY;
+                       }
+               } else if ( state == QS_INKEY ) {
+                       if ( *ptr == '=' ) {
+                               mptr->key = unescape( begin , ptr-begin );
+                               state = QS_WAITVAL;
+                       } else if ( *ptr == '&' ) {
+                               mptr->key = unescape( begin , ptr-begin );
+                               mptr->value = t0malloc(sizeof(char));
+                               mptr++;
+                               state = QS_WAITKEY;
+                       }
+               } else if ( state == QS_WAITVAL ) {
+                       if ( *ptr == '&' ) {
+                               mptr->value = t0malloc(sizeof(char));
+                               state = QS_WAITKEY;
+                               mptr++;
+                       } else {
+                               begin = ptr;
+                               state = QS_INVAL;
+                       }
+               } else if ( state == QS_INVAL ) {
+                       if ( *ptr == '&' ) {
+                               mptr->value = unescape( begin , ptr-begin );
+                               mptr++;
+                               state = QS_WAITKEY;
+                       } 
+               } else
+                       tlog( TL_CRIT|TL_EXIT,"Wrong state of QUERY_STRING parser");
+
+               ptr++;
+       }
+
+       if ( state == QS_INVAL ) {
+               mptr->value = unescape( begin , ptr-begin );
+               mptr++;
+       } if ( state == QS_INKEY ) {
+               mptr->key = unescape( begin , ptr-begin );
+               mptr->value = t0malloc(sizeof(char));
+               mptr++;
+       } else if ( state == QS_WAITVAL ) {
+               mptr->value = t0malloc(sizeof(char));
+       }
+
+       return mptr - *m;
+}