/* name: stritem.c purpose: one way to manage string items used with CHTML in C. author: george carrette 23-NOV-96 $Id: stritem.c,v 1.22 1998/05/21 18:23:00 gjc Exp $ */ #include #include #include #include #include "chtml.h" #ifndef CHTML_STRITEM_INIT_PUSH /* 1 = begining of list (LIFO) more efficient. 2 = end of list (FIFO) looks cleaner to some people. */ #define CHTML_STRITEM_INIT_PUSH 2 #endif CHTML_STRITEM chtml_stritem_init(char *name, CHTML_STRITEM *place, CHTML_STRITEM *list) {CHTML_STRITEM p; p = (CHTML_STRITEM) malloc(sizeof(struct chtml_stritem)); p->namelen = strlen(name); p->name = (char *) malloc(p->namelen + 1); strcpy(p->name,name); p->place = place; p->first = NULL; p->last = NULL; p->current = NULL; p->next = NULL; #if (CHTML_STRITEM_INIT_PUSH == 1) if (list) {p->next = *list; *list = p;} #endif #if (CHTML_STRITEM_INIT_PUSH == 2) if (list) if (!*list) *list = p; else {CHTML_STRITEM l; for(l = *list;l->next;l = l->next); l->next = p;} #endif if (place) *place = p; return(p);} void chtml_stritem_insert(CHTML_STRITEM p,char *start,char *end) {size_t len; struct chtml_str *s; len = (end) ? end - start : strlen(start); s = (struct chtml_str *) malloc(sizeof(struct chtml_str)); s->value = (char *) malloc(len+1); memcpy(s->value,start,len); s->value[len] = 0; s->next = NULL; if (p->last) {p->last->next = s; p->last = s;} else p->first = p->last = p->current = s;} void chtml_stritem_update(CHTML_STRITEM p,char *start,char *end) {size_t len; struct chtml_str *s; if (p->last) {s = p->last; free(s->value); len = (end) ? end - start : strlen(start); s->value = (char *) malloc(len+1); memcpy(s->value,start,len); s->value[len] = 0;} else chtml_stritem_insert(p,start,end);} void chtml_stritem_kinsert(CHTML_STRITEM *table,char *key, char *start,char *end) {CHTML_STRITEM x; if (!(x = chtml_stritem_getem(key,*table))) x = chtml_stritem_init(key,NULL,table); chtml_stritem_insert(x,start,end);} void chtml_stritem_kupdate(CHTML_STRITEM *table,char *key, char *start,char *end) {CHTML_STRITEM x; if (!(x = chtml_stritem_getem(key,*table))) x = chtml_stritem_init(key,NULL,table); chtml_stritem_update(x,start,end);} void chtml_stritem_rewind(CHTML_STRITEM p) {CHTML_STRITEM l; for(l=p;l;l = l->next) l->current = l->first;} void chtml_stritem_free(CHTML_STRITEM *p) {CHTML_STRITEM l,lnext; struct chtml_str *s,*snext; for(l = *p;l;l = lnext) {lnext = l->next; for(s=l->first;s;s = snext) {snext = s->next; free(s->value); free(s);} free(l->name); if (l->place) *l->place = NULL; free(l);} *p = NULL;} CHTML_STRITEM chtml_stritem_getemsub(char *key,char *end,CHTML_STRITEM tbl) {CHTML_STRITEM l; int keylen; keylen = (end) ? (end - key) : strlen(key); if (keylen < 0) return(NULL); for(l=tbl;l;l = l->next) if ((keylen == l->namelen) && (memcmp(key,l->name,keylen) == 0)) return(l); return(NULL);} CHTML_STRITEM chtml_stritem_getem(char *key,CHTML_STRITEM tbl) {CHTML_STRITEM l; for(l=tbl;l;l = l->next) if (strcmp(key,l->name) == 0) return(l); return(NULL);} char *chtml_stritem_get(char *key,CHTML_STRITEM tbl) {CHTML_STRITEM l; char *retval = key,*pkey; pkey = (key[0] == '.') ? &key[1] : key; if ((l = chtml_stritem_getem(pkey,tbl))) {if (l->current) {retval = l->current->value; if (l->current->next && (pkey == key)) l->current = l->current->next;}} return(retval);} char *chtml_stritem_getd(char *key,CHTML_STRITEM tbl,char *defaultv) {CHTML_STRITEM l; char *retval = defaultv,*pkey; pkey = (key[0] == '.') ? &key[1] : key; if ((l = chtml_stritem_getem(pkey,tbl))) {if (l->current) {retval = l->current->value; if (l->current->next && (pkey == key)) l->current = l->current->next;}} return(retval);} long chtml_stritem_len(CHTML_STRITEM p) {struct chtml_str *s; long n; for(n=0,s=p->current;s;s = s->next) ++n; return(n);} void chtml_stritem_debug_print(CHTML_STRITEM tbl) {CHTML_STRITEM l; struct chtml_str *s,*n; for(l=tbl;l;l = l->next) {printf("%s =",l->name); for(s=l->first;s;s=n) {n = s->next; printf(" %s%s",s->value,(n) ? "," : "");} printf("\n");}} void chtml_stritem_kinsert_qs(CHTML_STRITEM *table,char *s) {char *start,*end,*next,*ptr,*key,*value; for(start=s;*start;start=next) {if ((ptr = strchr(start,'&'))) {end = ptr; next = ptr+1;} else {end = &start[strlen(start)]; next = end;} if ((ptr = memchr(start,'=',end-start))) {key = chtml_url_decode(start,ptr); value = chtml_url_decode(ptr+1,end);} else {key = chtml_url_decode(start,end); value = chtml_url_decode("",NULL);} chtml_stritem_kinsert(table,key,value,NULL); free(key); free(value);}} void chtml_stritem_kinsertl(CHTML_STRITEM *table,char *key,long value) {char tmp[100]; sprintf(tmp,"%ld",value); chtml_stritem_kinsert(table,key,tmp,NULL);} int chtml_stritem_available(char *x,CHTML_STRITEM table) {CHTML_STRITEM l; if ((l = chtml_stritem_getem(x,table)) && (l->current)) return(1); else return(0);} int chtml_stritem_locate(char *value,CHTML_STRITEM list) {struct chtml_str *l; long i; for(i=0,l=list->current;l;l = l->next,++i) if (strcmp(value,l->value) == 0) return(i); return(-1);} void chtml_stritem_copy(CHTML_STRITEM *target_table, CHTML_STRITEM source_table, char *prefix) {CHTML_STRITEM l,x; struct chtml_str *s,*n; char *target_key; for(l=source_table;l;l = l->next) {if ((!prefix) || (!*prefix)) target_key = l->name; else {target_key = (char *) malloc(strlen(prefix) + strlen(l->name) + 1); strcpy(target_key,prefix); strcat(target_key,l->name);} if (!(x = chtml_stritem_getem(target_key,*target_table))) x = chtml_stritem_init(target_key,NULL,target_table); if (l->name != target_key) free(target_key); for(s=l->first;s;s=n) {n = s->next; chtml_stritem_insert(x,s->value,NULL);}}} void chtml_stritem_kinsertlr(CHTML_STRITEM *table,char *k,long start,long end) {long index; for(index = start; index <= end; ++index) chtml_stritem_kinsertl(table,k,index);} long chtml_stritem_available_len(char *key,CHTML_STRITEM table) {CHTML_STRITEM item; if ((item = chtml_stritem_getem(key,table))) return(chtml_stritem_len(item)); else return(0);} struct get_qs_cb_arg {char *buffer; size_t maxlen; size_t curlen; int growflag; int myflag;}; static char *get_qs_mallocator(size_t len,void *cb_arg) {struct get_qs_cb_arg *arg = (struct get_qs_cb_arg *) cb_arg; size_t curlen,next,maxlen; char *new; curlen = arg->curlen; next = curlen + len; if (next < arg->maxlen) {arg->curlen = next - 1; return(&arg->buffer[curlen]);} else if (!arg->growflag) return(NULL); else {maxlen = arg->maxlen * 2; if (next >= maxlen) maxlen = next+1; if (!(new = (char *) realloc(arg->buffer,maxlen))) return(NULL); arg->buffer = new; arg->curlen = next - 1; return(&arg->buffer[curlen]);}} static char *insert_failed(struct get_qs_cb_arg *a) {if (a->myflag) free(a->buffer); a->buffer = NULL; return(NULL);} static int insert_list(CHTML_STRITEM l,struct get_qs_cb_arg *a,int *inflag) {struct chtml_str *s; char *ptr; for(s = l->first;s; s = s->next) {if (*inflag) {if (!(ptr = get_qs_mallocator(2,a))) return(1); strcpy(ptr,"&");} else *inflag = 1; if (!chtml_url_encode_cb(l->name,NULL,get_qs_mallocator,a)) return(1); if (!(ptr = get_qs_mallocator(2,a))) return(1); strcpy(ptr,"="); if (!chtml_url_encode_cb(s->value,NULL,get_qs_mallocator,a)) return(1);} return(0);} char *chtml_stritem_get_qs(CHTML_STRITEM table,char *buffer,size_t buflen, ...) {CHTML_STRITEM l; struct get_qs_cb_arg arg; int inflag,nkeys; char *keyname; va_list keylist; if (buffer) {arg.maxlen = buflen; arg.buffer = buffer; arg.curlen = 0; arg.growflag = 0; arg.myflag = 0;} else if (buflen > 0) {arg.maxlen = buflen; arg.buffer = (char *) malloc(arg.maxlen); arg.curlen = 0; arg.growflag = 0; arg.myflag = 1;} else {arg.maxlen = 100; arg.buffer = (char *) malloc(arg.maxlen); arg.curlen = 0; arg.growflag = 1; arg.myflag = 1;} if (!arg.buffer) return(NULL); va_start(keylist,buflen); for(inflag=0,nkeys=0; (keyname = va_arg(keylist,char *)); ++nkeys) if ((l = chtml_stritem_getem(keyname,table)) && insert_list(l,&arg,&inflag)) return(insert_failed(&arg)); va_end(keylist); if (nkeys) return(arg.buffer); for(inflag=0,l=table;l;l = l->next) if (insert_list(l,&arg,&inflag)) return(insert_failed(&arg)); return(arg.buffer);}