Module: sip-router
Branch: andrei/type_conversion
Commit: 54b54c1fcf1f5f6967859890cf345a70cc0aab7f
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=54b54c1…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)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;