Module: sip-router Branch: andrei/type_conversion Commit: 54b54c1fcf1f5f6967859890cf345a70cc0aab7f URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=54b54c1f...
Author: Andrei Pelinescu-Onciul andrei@iptel.org Committer: Andrei Pelinescu-Onciul andrei@iptel.org Date: Tue Apr 28 12:00:04 2009 +0200
core expr eval: str automatic conversion to int
(int)"" = 0 (int)"<number>" = <number> (e.g. (int)"123" = 123) (int)"<non-numeric>" = 0 (e.g. (int)"abc" = 0)
---
rvalue.c | 44 +++++++++++++++++++++++++++++++++++++------- 1 files changed, 37 insertions(+), 7 deletions(-)
diff --git a/rvalue.c b/rvalue.c index 259d921..e815c24 100644 --- a/rvalue.c +++ b/rvalue.c @@ -24,6 +24,9 @@ * -------- * 2008-12-01 initial version (andrei) * 2009-04-24 added support for defined, strempty, strlen (andrei) + * 2009-04-28 int and str automatic conversions: (int)undef=0, + * (str)undef="", (int)""=0, (int)"123"=123, (int)"abc"=0 + * (andrei) */
#include "rvalue.h" @@ -686,12 +689,19 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg, avp_t* r_avp; int_str avp_val; pv_value_t pval; + str tmp; + str* s; + int r; + int destroy_pval; + destroy_pval=0; + s=0; switch(rv->type){ case RV_INT: *i=rv->v.l; break; case RV_STR: + s=&rv->v.s; goto rv_str; case RV_BEXPR: *i=eval_expr(h, rv->v.bexpr, msg); @@ -707,14 +717,23 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg, *i=0; break; case RV_SEL: + r=run_select(&tmp, &rv->v.sel, msg); + if (unlikely(r!=0)){ + if (r<0) + goto eval_error; + else /* i>0 => undefined */ + goto undef; + } + s=&tmp; goto rv_str; case RV_AVP: if (unlikely(cache && cache->cache_type==RV_CACHE_AVP)){ if (likely(cache->val_type==RV_INT)){ *i=cache->c.avp_val.n; - }else if (cache->val_type==RV_STR) + }else if (cache->val_type==RV_STR){ + s=&cache->c.avp_val.s; goto rv_str; - else if (cache->val_type==RV_NONE) + }else if (cache->val_type==RV_NONE) goto undef; else goto error_cache; }else{ @@ -722,6 +741,7 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg, &avp_val, rv->v.avps.index); if (likely(r_avp)){ if (unlikely(r_avp->flags & AVP_VAL_STR)){ + s=&avp_val.s; goto rv_str; }else{ *i=avp_val.n; @@ -736,9 +756,10 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg, if (likely((cache->val_type==RV_INT) || (cache->c.pval.flags & PV_VAL_INT))){ *i=cache->c.pval.ri; - }else if (cache->val_type==RV_STR) + }else if (cache->val_type==RV_STR){ + s=&cache->c.pval.rs; goto rv_str; - else if (cache->val_type==RV_NONE) + }else if (cache->val_type==RV_NONE) goto undef; else goto error_cache; }else{ @@ -748,7 +769,8 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg, *i=pval.ri; pv_value_destroy(&pval); }else if (likely(pval.flags & PV_VAL_STR)){ - pv_value_destroy(&pval); + destroy_pval=1; /* we must pv_value_destroy() later*/ + s=&pval.rs; goto rv_str; }else{ /* no PV_VAL_STR and no PV_VAL_INT => undef @@ -775,8 +797,16 @@ error_cache: BUG("invalid cached value:cache type %d, value type %d\n", cache?cache->cache_type:0, cache?cache->val_type:0); rv_str: - /* rv is of string type => error */ - /* ERR("string in int expression\n"); */ + /* rv is of string type => try to convert it to int */ + /* if "" => 0 (most likely case) */ + if (likely(s->len==0)) *i=0; + else if (unlikely(str2sint(s, i)!=0)){ + /* error converting to int => non numeric => 0 */ + *i=0; + } + if (destroy_pval) + pv_value_destroy(&pval); + return 0; error: *i=0; return -1;