Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals

vars.c

00001 /*
00002  * Copyright (c) 2005, 2006 by KoanLogic s.r.l. <http://www.koanlogic.com>
00003  * All rights reserved.
00004  *
00005  * This file is part of KLone, and as such it is subject to the license stated
00006  * in the LICENSE file which you have received as part of this distribution.
00007  *
00008  * $Id: vars.c,v 1.28 2007/10/26 11:21:51 tho Exp $
00009  */
00010 
00011 #include "klone_conf.h"
00012 #include <sys/types.h>
00013 #include <stdlib.h>
00014 #include <u/libu.h>
00015 #include <klone/vars.h>
00016 #include <klone/varprv.h>
00017 #include <klone/utils.h>
00018 
00019 TAILQ_HEAD(var_list_s, var_s);
00020 
00021 struct vars_s
00022 {
00023     struct var_list_s list;     /* list of variables (var_t) */
00024     size_t count;               /* # of vars in the list     */
00025 };
00026 
00039 u_string_t *vars_get_value_s(vars_t *vs, const char *name)
00040 {
00041     var_t *v = NULL;
00042 
00043     dbg_err_if (vs == NULL);
00044     dbg_err_if (name == NULL);
00045 
00046     dbg_err_if((v = vars_get(vs, name)) == NULL);
00047 
00048     return var_get_value_s(v);
00049 err:
00050     return NULL;
00051 }
00052 
00053 int vars_create(vars_t **pvs)
00054 {
00055     vars_t *vs = NULL;
00056 
00057     dbg_err_if (pvs == NULL);
00058 
00059     vs = u_zalloc(sizeof(vars_t));
00060     dbg_err_if(vs == NULL);
00061 
00062     TAILQ_INIT(&vs->list);
00063 
00064     *pvs = vs;
00065 
00066     return 0;
00067 err:
00068     if(vs)
00069         vars_free(vs);
00070     return ~0;
00071 }
00072 
00073 int vars_free(vars_t *vs)
00074 {
00075     var_t *v;
00076 
00077     if(vs)
00078     {
00079         /* free all variables */
00080         while((v = TAILQ_FIRST(&vs->list)) != NULL)
00081         {
00082             vars_del(vs, v);
00083             var_free(v);
00084         }
00085         U_FREE(vs);
00086     }
00087 
00088     return 0;
00089 }
00090 
00091 int vars_add(vars_t *vs, var_t *v)
00092 {
00093     TAILQ_INSERT_TAIL(&vs->list, v, np);
00094     vs->count++;
00095 
00096     return 0;
00097 }
00098 
00099 int vars_del(vars_t *vs, var_t *v)
00100 {
00101     dbg_return_if (vs == NULL, ~0);
00102     dbg_return_if (v == NULL, ~0);
00103    
00104     TAILQ_REMOVE(&vs->list, v, np);
00105     vs->count--;
00106 
00107     return 0;
00108 }
00109 
00121 var_t *vars_getn(vars_t *vs, size_t i)
00122 {
00123     var_t *v;
00124 
00125     dbg_goto_if (vs == NULL, notfound);
00126     dbg_goto_if (i >= vs->count, notfound); /* out of bounds */
00127 
00128     TAILQ_FOREACH(v, &vs->list, np)
00129     {
00130         if(i-- == 0)
00131             return v;
00132     }
00133 
00134 notfound:
00135     return NULL;
00136 }
00137 
00148 size_t vars_count(vars_t *vs)
00149 {
00150     dbg_return_if (vs == NULL, 0);
00151 
00152     return vs->count;
00153 }
00154 
00166 size_t vars_countn(vars_t *vs, const char *name)
00167 {
00168     var_t *v;
00169     size_t c = 0;
00170 
00171     dbg_return_if (vs == NULL || name == NULL, 0);
00172 
00173     TAILQ_FOREACH(v, &vs->list, np)
00174     {
00175         if(strcasecmp(u_string_c(v->sname), name) == 0)
00176             c++;
00177     }
00178 
00179     return c;
00180 }
00181 
00195 int vars_add_urlvar(vars_t *vs, const char *cstr, var_t **v)
00196 {
00197     enum { NAMESZ = 256, VALSZ = 4096 };
00198     char sname[NAMESZ], svalue[VALSZ];
00199     char *val, *str = NULL, *name = sname, *value = svalue;
00200     var_t *var = NULL;
00201     ssize_t vsz;
00202 
00203     dbg_return_if (vs == NULL, ~0);
00204     dbg_return_if (cstr == NULL, ~0);
00205     /* v may be NULL */
00206         
00207     /* dup the string so we can modify it */
00208     str = u_strdup(cstr);
00209     dbg_err_if(str == NULL);
00210 
00211     val = strchr(str, '=');
00212     dbg_err_if(val == NULL);
00213 
00214     /* zero-term the name part and set the value pointer */
00215     *val++ = 0; 
00216 
00217     /* if the buffer on the stack is too small alloc a bigger one */
00218     if(strlen(str) >= NAMESZ)
00219         dbg_err_if((name = u_zalloc(1 + strlen(str))) == NULL);
00220 
00221     /* if the buffer on the stack is too small alloc a bigger one */
00222     if(strlen(val) >= VALSZ)
00223         dbg_err_if((value = u_zalloc(1 + strlen(val))) == NULL);
00224 
00225     /* url-decode var name */
00226     dbg_err_if(u_urlncpy(name, str, strlen(str), URLCPY_DECODE) <= 0);
00227 
00228     /* url-decode var value */
00229     dbg_err_if((vsz = u_urlncpy(value, val, strlen(val), URLCPY_DECODE)) <= 0);
00230 
00231     /* dbg("name: [%s]  value: [%s]", name, value); */
00232 
00233     dbg_err_if(var_bin_create(name, value, vsz, &var));
00234 
00235     /* push into the var list */
00236     dbg_err_if(vars_add(vs, var));
00237 
00238     if(v)
00239         *v = var;
00240 
00241     /* if the buffer has been alloc'd on the heap then free it */
00242     if(value && value != svalue)
00243         U_FREE(value);
00244 
00245     if(name && name != sname)
00246         U_FREE(name);
00247 
00248     U_FREE(str);
00249 
00250     return 0;
00251 err:
00252     if(value && value != svalue)
00253         U_FREE(value);
00254     if(name && name != sname)
00255         U_FREE(name);
00256     if(cstr)
00257         dbg("%s", cstr);
00258     U_FREE(str);
00259     if(var)
00260         var_free(var);
00261     return ~0;
00262 }
00263 
00264 int vars_add_strvar(vars_t *vs, const char *str)
00265 {
00266     char *eq, *dups = NULL;
00267     var_t *var = NULL;
00268 
00269     dbg_err_if (vs == NULL);
00270     dbg_err_if (str == NULL);
00271 
00272     /* dup the string (str is const) */
00273     dups = u_strdup(str);
00274     dbg_err_if(dups == NULL);
00275 
00276     /* search the '=' and replace it with a '\0' */
00277     eq = strchr(dups, '=');
00278     dbg_err_if(eq == NULL);
00279     *eq = 0;
00280 
00281     /* create a new var obj */
00282     dbg_err_if(var_create(dups, eq+1, &var));
00283 
00284     U_FREE(dups);
00285 
00286     /* push into the cookie list */
00287     dbg_err_if(vars_add(vs, var));
00288 
00289     return 0;
00290 err:
00291     U_FREE(dups);
00292     if(var)
00293         var_free(var);
00294     return ~0;
00295 }
00296 
00311 var_t *vars_geti(vars_t *vs, const char *var_name, size_t i)
00312 {
00313     var_t *v;
00314 
00315     dbg_goto_if (vs == NULL, notfound);
00316     dbg_goto_if (var_name == NULL, notfound);
00317 
00318     TAILQ_FOREACH(v, &vs->list, np)
00319     {
00320         if(strcasecmp(u_string_c(v->sname), var_name) == 0)
00321         {
00322             if(i-- == 0)
00323                 return v;
00324         }
00325     }
00326 
00327 notfound:
00328     return NULL;
00329 }
00330 
00344 var_t *vars_get(vars_t *vs, const char *var_name)
00345 {
00346     dbg_return_if (vs == NULL, NULL);
00347     dbg_return_if (var_name == NULL, NULL);
00348 
00349     return vars_geti(vs, var_name, 0);
00350 }
00351 
00367 int vars_geti_value_i(vars_t *vs, const char *name, size_t ith)
00368 {
00369     const char *v;
00370 
00371     dbg_return_if (vs == NULL, 0);
00372     dbg_return_if (name == NULL, 0);
00373 
00374     v = vars_geti_value(vs, name, ith);
00375     if(v == NULL)
00376         return 0;
00377     else
00378         return atoi(v);
00379 }
00380 
00394 u_string_t *vars_geti_value_s(vars_t *vs, const char *name, size_t ith)
00395 {
00396     var_t *v = NULL;
00397 
00398     dbg_err_if (vs == NULL);
00399     dbg_err_if (name == NULL);
00400 
00401     dbg_err_if((v = vars_geti(vs, name, ith)) == NULL);
00402 
00403     return var_get_value_s(v);
00404 err:
00405     return NULL;
00406 }
00407 
00421 int vars_get_value_i(vars_t *vs, const char *name)
00422 {
00423     dbg_return_if (vs == NULL, 0);
00424     dbg_return_if (name == NULL, 0);
00425 
00426     return vars_geti_value_i(vs, name, 0);
00427 }
00428 
00444 const char *vars_geti_value(vars_t *vs, const char *name, size_t ith)
00445 {
00446     var_t *v;
00447 
00448     dbg_return_if (vs == NULL, NULL);
00449     dbg_return_if (name == NULL, NULL);
00450     
00451     v = vars_geti(vs, name, ith);
00452 
00453     return  v ? var_get_value(v) : NULL;
00454 }
00455 
00469 const char *vars_get_value(vars_t *vs, const char *name)
00470 {
00471     dbg_return_if (vs == NULL, NULL);
00472     dbg_return_if (name == NULL, NULL);
00473 
00474     return vars_geti_value(vs, name, 0);
00475 }
00476 
00490 void vars_foreach(vars_t *vs, int (*cb)(var_t *, void *), void *arg)
00491 {
00492     var_t *v;
00493 
00494     dbg_ifb (vs == NULL) return;
00495     dbg_ifb (cb == NULL) return;
00496 
00497     TAILQ_FOREACH(v, &vs->list, np)
00498     {
00499         if(cb(v, arg))
00500             break;
00501     }
00502 
00503     return;
00504 }