/** * data.c * * Copyright (C) 2003 - 2008 Bojan Smojver, Rexursive * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 2.1 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * */ #include "private.h" /* * Data creation and transformation functions */ /* single data element from a string, no copying */ rxv_spin_data_t *rxv_spin_datum(apr_pool_t *pool,const char *str, rxv_spin_data_t *data){ apr_size_t size; if(!((pool || data) && str) || (size=strlen(str))==RXV_SPIN_ROWS) return NULL; /* allocate data if required */ if(!data) data=apr_pcalloc(pool,sizeof(*data)); data->size=size; data->data=(char *)str; return data; } /* single data element from a counted string, no copying */ rxv_spin_data_t *rxv_spin_mdatum(apr_pool_t *pool,const char *str, apr_size_t size,rxv_spin_data_t *data){ if(!((pool || data) && str) || size==RXV_SPIN_ROWS || *(str+size)!='\0') return NULL; /* allocate data if required */ if(!data) data=apr_pcalloc(pool,sizeof(*data)); data->size=size; data->data=(char *)str; return data; } /* string from single */ char *rxv_spin_string(rxv_spin_data_t *single){ if(!single || single->size==RXV_SPIN_ROWS) return NULL; return single->data; } /* hash table from rows */ apr_hash_t *rxv_spin_guts(rxv_spin_data_t *rows){ if(!(rows && rows->size==RXV_SPIN_ROWS)) return NULL; return rows->cols; } /* size of single */ apr_size_t rxv_spin_size(rxv_spin_data_t *data){ if(!data) return 0; if(data->size==RXV_SPIN_ROWS){ apr_array_header_t *a; apr_hash_index_t *hi=apr_hash_first(apr_hash_pool_get(data->cols), data->cols); if(hi){ apr_hash_this(hi,NULL,NULL,(void **)&a); return (apr_size_t)a->nelts; } else{ return 0; } } else{ return data->size; } } /* column of rows from other data elements, no copying */ rxv_spin_data_t *rxv_spin_column(apr_pool_t *pool,const char *name, rxv_spin_data_t *data,...){ va_list ap; rxv_spin_data_t *rows,*d; apr_array_header_t *a; int size=0; if(!(pool && name)) return NULL; /* allocate rows if required */ rows=data?data:apr_pcalloc(pool,sizeof(*rows)); /* count the elements first */ va_start(ap,data); while((d=va_arg(ap,rxv_spin_data_t*))) size++; va_end(ap); rows->size=RXV_SPIN_ROWS; rows->cols=apr_hash_make(pool); apr_hash_set(rows->cols,name,APR_HASH_KEY_STRING, a=apr_array_make(pool,size,sizeof(*d))); /* populate array */ va_start(ap,data); while((d=va_arg(ap,rxv_spin_data_t*))) *((rxv_spin_data_t *)apr_array_push(a))=*d; va_end(ap); return rows; } /* column of rows from string by parsing, no copying */ rxv_spin_data_t *rxv_spin_parse(apr_pool_t *pool,const char *name, char *str,const char *sep, rxv_spin_data_t *data){ char *t,*last=NULL; rxv_spin_data_t *p; apr_array_header_t *a; if(!(pool && name && str && sep)) return NULL; a=apr_array_make(pool,10,sizeof(*p)); /* parse the string and store it into an array */ for(t=apr_strtok(str,sep,&last);t;t=apr_strtok(NULL,sep,&last)){ p=apr_array_push(a); p->size=strlen(t); p->data=t; } if(apr_is_empty_array(a)) return NULL; /* allocate data if required */ if(!data) data=apr_pcalloc(pool,sizeof(*data)); data->size=RXV_SPIN_ROWS; data->cols=apr_hash_make(pool); apr_hash_set(data->cols,name,APR_HASH_KEY_STRING,a); return data; } /* column of rows from an array of nul terminated strings, no copying */ rxv_spin_data_t *rxv_spin_array(apr_pool_t *pool,const char *name, apr_array_header_t *arr,rxv_spin_data_t *data){ rxv_spin_data_t *p; apr_array_header_t *a; int i; if(!(pool && name && arr)) return NULL; /* allocate data if required */ if(!data) data=apr_pcalloc(pool,sizeof(*data)); data->size=RXV_SPIN_ROWS; data->cols=apr_hash_make(pool); apr_hash_set(data->cols,name,APR_HASH_KEY_STRING, a=apr_array_make(pool,arr->nelts,sizeof(*p))); /* copy content */ for(i=0;inelts;i++){ char *buf=apr_pstrdup(pool,*((char**)arr->elts+i)); p=apr_array_push(a); p->size=strlen(buf); p->data=buf; } return data; } /* column of rows from a brigade, full copying */ rxv_spin_data_t *rxv_spin_brigade(apr_pool_t *pool,const char *name, apr_bucket_brigade *bb, rxv_spin_data_t *data){ apr_bucket *b; rxv_spin_data_t *p; apr_array_header_t *a; int size=0; if(!(pool && name && bb)) return NULL; /* allocate data if required */ if(!data) data=apr_pcalloc(pool,sizeof(*data)); /* count the number of buckets */ for(b=APR_BRIGADE_FIRST(bb);b!=APR_BRIGADE_SENTINEL(bb);b=APR_BUCKET_NEXT(b)) size++; data->size=RXV_SPIN_ROWS; data->cols=apr_hash_make(pool); apr_hash_set(data->cols,name,APR_HASH_KEY_STRING, a=apr_array_make(pool,size,sizeof(*p))); /* copy content */ for(b=APR_BRIGADE_FIRST(bb);b!=APR_BRIGADE_SENTINEL(bb);b=APR_BUCKET_NEXT(b)){ char *buf=apr_palloc(pool,b->length); const char *str; apr_size_t pos=0,len; while(poslength){ len=b->length-pos; if(apr_bucket_read(b,&str,&len,APR_BLOCK_READ)!=APR_SUCCESS) return NULL; memcpy(buf+pos,str,len); pos+=len; } p=apr_array_push(a); p->size=strlen(buf); p->data=buf; } return data; } /* create an empty column of rows */ rxv_spin_data_t *rxv_spin_null(apr_pool_t *pool,const char *name, apr_size_t size,rxv_spin_data_t *data){ apr_array_header_t *a; apr_size_t i; if(!(pool && name && size>0)) return NULL; /* allocate data if required */ if(!data) data=apr_pcalloc(pool,sizeof(*data)); data->size=RXV_SPIN_ROWS; data->cols=apr_hash_make(pool); apr_hash_set(data->cols,name,APR_HASH_KEY_STRING, a=apr_array_make(pool,(int)size,sizeof(*data))); for(i=0;isize!=RXV_SPIN_ROWS || !(hi=apr_hash_first(pool,s->cols))) return NULL; apr_hash_this(hi,NULL,NULL,(void **)&a); if(a->nelts>size) size=a->nelts; } va_end(ap); /* allocate rows if required */ rows=data?data:apr_pcalloc(pool,sizeof(*rows)); rows->size=RXV_SPIN_ROWS; rows->cols=apr_hash_make(pool); /* populate */ va_start(ap,data); while((s=va_arg(ap,rxv_spin_data_t*))){ apr_hash_index_t *hi; apr_array_header_t *a; char *k; apr_ssize_t len; for(hi=apr_hash_first(pool,s->cols);hi;hi=apr_hash_next(hi)){ apr_hash_this(hi,(const void **)&k,&len,(void **)&a); apr_hash_set(rows->cols,k,len,a); while(a->neltssize==RXV_SPIN_ROWS)) return 0; /* allocate rows if required */ iter=apr_pcalloc(pool,sizeof(*iter)); iter->rows=rows; iter->size=-1; /* find size */ va_start(ap,rows); while((s=va_arg(ap,const char*))){ c=va_arg(ap,rxv_spin_curs_t **); if(!(a=apr_hash_get(rows->cols,s,APR_HASH_KEY_STRING))) return 0; if(!*c) *c=apr_pcalloc(pool,sizeof(**c)); (*c)->iter=iter; (*c)->data=a; if(iter->size<=0) iter->size=(*c)->data->nelts; } va_end(ap); return iter->index>=iter->size?0:(apr_size_t)(iter->index+1); } /* get next row */ apr_size_t rxv_spin_next(rxv_spin_curs_t *curs){ rxv_spin_iter_t *iter; if(!curs) return 0; iter=curs->iter; if(iter->indexsize) iter->index++; return iter->index>=iter->size?0:(apr_size_t)(iter->index+1); } /* get a piece of data */ rxv_spin_data_t *rxv_spin_this(rxv_spin_curs_t *curs){ if(!(curs && curs->iter->index<=curs->iter->size)) return NULL; return ((rxv_spin_data_t *)curs->data->elts)+curs->iter->index; } /* get an entry from rows */ rxv_spin_data_t *rxv_spin_entry(rxv_spin_data_t *rows,const char *name, apr_size_t index){ apr_array_header_t *a; if(!(rows && rows->size==RXV_SPIN_ROWS && name && index)) return NULL; if(!(a=apr_hash_get(rows->cols,name,APR_HASH_KEY_STRING)) || a->nelts<(int)index) return NULL; return ((rxv_spin_data_t *)a->elts)+index-1; } /* resize rows */ rxv_spin_data_t *rxv_spin_resize(rxv_spin_data_t *data,apr_size_t size){ apr_hash_index_t *hi; apr_array_header_t *a; if(!(data && size>=0 && data->size==RXV_SPIN_ROWS)) return NULL; for(hi=apr_hash_first(apr_hash_pool_get(data->cols),data->cols); hi;hi=apr_hash_next(hi)){ apr_hash_this(hi,NULL,NULL,(void **)&a); if(a->nelts>(int)size) while(a->nelts>(int)size) apr_array_pop(a); else while(a->nelts<(int)size) apr_array_push(a); } return data; } /* copy data (full copy) */ rxv_spin_data_t *rxv_spin_copy(apr_pool_t *pool,rxv_spin_data_t *src, rxv_spin_data_t *data){ int i; apr_hash_index_t *hi; char *k,*s; void *v; apr_ssize_t len; if(!(pool && src)) return NULL; /* allocate data if required */ if(!data) data=apr_pcalloc(pool,sizeof(*data)); if(src->size==RXV_SPIN_ROWS){ apr_array_header_t *a,*b; data->cols=apr_hash_make(pool); for(hi=apr_hash_first(pool,src->cols);hi;hi=apr_hash_next(hi)){ apr_hash_this(hi,(const void **)&k,&len,&v); s=apr_pstrmemdup(pool,k,len); b=apr_array_make(pool,(a=(apr_array_header_t *)v)->nelts,sizeof(*data)); apr_hash_set(data->cols,s,len,b); for(i=0;inelts;i++) rxv_spin_copy(pool,((rxv_spin_data_t *)a->elts)+i,apr_array_push(b)); } data->size=RXV_SPIN_ROWS; } else{ data->data=apr_pstrmemdup(pool,src->data,src->size); data->size=src->size; } return data; } /* string to upper/lower functions */ char *rxv_spin_slower(const char *str){ char *p; if(!str) return NULL; for(p=(char *)str;*p;p++) *p=tolower(*p); return (char *)str; } char *rxv_spin_supper(const char *str){ char *p; if(!str) return NULL; for(p=(char *)str;*p;p++) *p=toupper(*p); return (char *)str; } /* string trim function */ char *rxv_spin_strim(const char *str,rxv_spin_trim_e what){ char *tmp,*s=(char *)str; apr_size_t size; if(!str) return NULL; size=strlen(str); if(what&RXV_SPIN_TRIM_LEFT){ for(tmp=s;size>0 && apr_isspace(*tmp);tmp++) size--; s=tmp; } if(what&RXV_SPIN_TRIM_RIGHT) for(tmp=s+size-1;size>0 && apr_isspace(*tmp);tmp--){ *tmp='\0'; size--; } return s; }