Main Page | Modules | File List | 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.30 2008/04/25 19:44:48 tat 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     u_list_t *list;              /* list of variables (var_t) */
00024     int flags;
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     dbg_err_if(u_list_create(&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_set_flags(vars_t *vs, int flags)
00074 {
00075     dbg_err_if (vs == NULL);
00076 
00077     vs->flags = flags;
00078 
00079     return 0;
00080 err:
00081     return ~0;
00082 }
00083 
00084 int vars_free(vars_t *vs)
00085 {
00086     var_t *v;
00087     int t;
00088 
00089     if(vs)
00090     {
00091         /* if the var_t objects are owned by this vars_t then free them all */
00092         if((vs->flags & VARS_FLAG_FOREIGN) == 0)
00093         {
00094             /* free all variables */
00095             for(t = 0; (v = u_list_get_n(vs->list, t)) != NULL; ++t)
00096                 var_free(v);
00097         }
00098 
00099         if(vs->list)
00100             u_list_free(vs->list);
00101 
00102         U_FREE(vs);
00103     }
00104 
00105     return 0;
00106 }
00107 
00108 int vars_add(vars_t *vs, var_t *v)
00109 {
00110     dbg_err_if(vs == NULL);
00111     dbg_err_if(v == NULL);
00112 
00113     dbg_err_if(u_list_add(vs->list, v));
00114 
00115     return 0;
00116 err:
00117     return ~0;
00118 }
00119 
00120 int vars_del(vars_t *vs, var_t *v)
00121 {
00122     dbg_err_if(vs == NULL);
00123     dbg_err_if(v == NULL);
00124    
00125     dbg_err_if(u_list_del(vs->list, v));
00126 
00127     return 0;
00128 err:
00129     return ~0;
00130 }
00131 
00143 var_t *vars_getn(vars_t *vs, size_t i)
00144 {
00145     dbg_goto_if (vs == NULL, notfound);
00146 
00147     dbg_goto_if (i >= u_list_count(vs->list), notfound); /* out of bounds */
00148 
00149     return u_list_get_n(vs->list, i);
00150 notfound:
00151     return NULL;
00152 }
00153 
00164 size_t vars_count(vars_t *vs)
00165 {
00166     dbg_return_if (vs == NULL, 0);
00167 
00168     return u_list_count(vs->list);
00169 }
00170 
00182 size_t vars_countn(vars_t *vs, const char *name)
00183 {
00184     var_t *v;
00185     size_t c = 0;
00186     int t;
00187 
00188     dbg_return_if (vs == NULL || name == NULL, 0);
00189 
00190     for(t = 0; (v = u_list_get_n(vs->list, t)) != NULL; ++t)
00191     {
00192         if(strcasecmp(u_string_c(v->sname), name) == 0)
00193             c++;
00194     }
00195 
00196     return c;
00197 }
00198 
00212 int vars_add_urlvar(vars_t *vs, const char *cstr, var_t **v)
00213 {
00214     enum { NAMESZ = 256, VALSZ = 4096 };
00215     char sname[NAMESZ], svalue[VALSZ];
00216     char *val, *str = NULL, *name = sname, *value = svalue;
00217     var_t *var = NULL;
00218     ssize_t vsz;
00219 
00220     dbg_return_if (vs == NULL, ~0);
00221     dbg_return_if (cstr == NULL, ~0);
00222     /* v may be NULL */
00223         
00224     /* dup the string so we can modify it */
00225     str = u_strdup(cstr);
00226     dbg_err_if(str == NULL);
00227 
00228     val = strchr(str, '=');
00229     dbg_err_if(val == NULL);
00230 
00231     /* zero-term the name part and set the value pointer */
00232     *val++ = 0; 
00233 
00234     /* if the buffer on the stack is too small alloc a bigger one */
00235     if(strlen(str) >= NAMESZ)
00236         dbg_err_if((name = u_zalloc(1 + strlen(str))) == NULL);
00237 
00238     /* if the buffer on the stack is too small alloc a bigger one */
00239     if(strlen(val) >= VALSZ)
00240         dbg_err_if((value = u_zalloc(1 + strlen(val))) == NULL);
00241 
00242     /* url-decode var name */
00243     dbg_err_if(u_urlncpy(name, str, strlen(str), URLCPY_DECODE) <= 0);
00244 
00245     /* url-decode var value */
00246     dbg_err_if((vsz = u_urlncpy(value, val, strlen(val), URLCPY_DECODE)) <= 0);
00247 
00248     /* dbg("name: [%s]  value: [%s]", name, value); */
00249 
00250     dbg_err_if(var_bin_create(name, value, vsz, &var));
00251 
00252     /* push into the var list */
00253     dbg_err_if(vars_add(vs, var));
00254 
00255     if(v)
00256         *v = var;
00257 
00258     /* if the buffer has been alloc'd on the heap then free it */
00259     if(value && value != svalue)
00260         U_FREE(value);
00261 
00262     if(name && name != sname)
00263         U_FREE(name);
00264 
00265     U_FREE(str);
00266 
00267     return 0;
00268 err:
00269     if(value && value != svalue)
00270         U_FREE(value);
00271     if(name && name != sname)
00272         U_FREE(name);
00273     if(cstr)
00274         dbg("%s", cstr);
00275     U_FREE(str);
00276     if(var)
00277         var_free(var);
00278     return ~0;
00279 }
00280 
00281 int vars_add_strvar(vars_t *vs, const char *str)
00282 {
00283     char *eq, *dups = NULL;
00284     var_t *var = NULL;
00285 
00286     dbg_err_if (vs == NULL);
00287     dbg_err_if (str == NULL);
00288 
00289     /* dup the string (str is const) */
00290     dups = u_strdup(str);
00291     dbg_err_if(dups == NULL);
00292 
00293     /* search the '=' and replace it with a '\0' */
00294     eq = strchr(dups, '=');
00295     dbg_err_if(eq == NULL);
00296     *eq = 0;
00297 
00298     /* create a new var obj */
00299     dbg_err_if(var_create(dups, eq+1, &var));
00300 
00301     U_FREE(dups);
00302 
00303     /* push into the cookie list */
00304     dbg_err_if(vars_add(vs, var));
00305 
00306     return 0;
00307 err:
00308     U_FREE(dups);
00309     if(var)
00310         var_free(var);
00311     return ~0;
00312 }
00313 
00328 var_t *vars_geti(vars_t *vs, const char *var_name, size_t i)
00329 {
00330     var_t *v;
00331     int t;
00332 
00333     dbg_goto_if (vs == NULL, notfound);
00334     dbg_goto_if (var_name == NULL, notfound);
00335 
00336     for(t = 0; (v = u_list_get_n(vs->list, t)) != NULL; ++t)
00337     {
00338         if(strcasecmp(u_string_c(v->sname), var_name) == 0)
00339         {
00340             if(i-- == 0)
00341                 return v;
00342         }
00343     }
00344 
00345 notfound:
00346     return NULL;
00347 }
00348 
00362 var_t *vars_get(vars_t *vs, const char *var_name)
00363 {
00364     dbg_return_if (vs == NULL, NULL);
00365     dbg_return_if (var_name == NULL, NULL);
00366 
00367     return vars_geti(vs, var_name, 0);
00368 }
00369 
00385 int vars_geti_value_i(vars_t *vs, const char *name, size_t ith)
00386 {
00387     const char *v;
00388 
00389     dbg_return_if (vs == NULL, 0);
00390     dbg_return_if (name == NULL, 0);
00391 
00392     v = vars_geti_value(vs, name, ith);
00393     if(v == NULL)
00394         return 0;
00395     else
00396         return atoi(v);
00397 }
00398 
00412 u_string_t *vars_geti_value_s(vars_t *vs, const char *name, size_t ith)
00413 {
00414     var_t *v = NULL;
00415 
00416     dbg_err_if (vs == NULL);
00417     dbg_err_if (name == NULL);
00418 
00419     dbg_err_if((v = vars_geti(vs, name, ith)) == NULL);
00420 
00421     return var_get_value_s(v);
00422 err:
00423     return NULL;
00424 }
00425 
00439 int vars_get_value_i(vars_t *vs, const char *name)
00440 {
00441     dbg_return_if (vs == NULL, 0);
00442     dbg_return_if (name == NULL, 0);
00443 
00444     return vars_geti_value_i(vs, name, 0);
00445 }
00446 
00462 const char *vars_geti_value(vars_t *vs, const char *name, size_t ith)
00463 {
00464     var_t *v;
00465 
00466     dbg_return_if (vs == NULL, NULL);
00467     dbg_return_if (name == NULL, NULL);
00468     
00469     v = vars_geti(vs, name, ith);
00470 
00471     return  v ? var_get_value(v) : NULL;
00472 }
00473 
00487 const char *vars_get_value(vars_t *vs, const char *name)
00488 {
00489     dbg_return_if (vs == NULL, NULL);
00490     dbg_return_if (name == NULL, NULL);
00491 
00492     return vars_geti_value(vs, name, 0);
00493 }
00494 
00508 void vars_foreach(vars_t *vs, int (*cb)(var_t *, void *), void *arg)
00509 {
00510     var_t *v;
00511     int t;
00512 
00513     dbg_ifb (vs == NULL) return;
00514     dbg_ifb (cb == NULL) return;
00515 
00516     for(t = 0; (v = u_list_get_n(vs->list, t)) != NULL; ++t)
00517     {
00518         if(cb(v, arg))
00519             break;
00520     }
00521 
00522     return;
00523 }
00524