core expr eval: str automatic conversion to int
authorAndrei Pelinescu-Onciul <andrei@iptel.org>
Tue, 28 Apr 2009 10:00:04 +0000 (12:00 +0200)
committerAndrei Pelinescu-Onciul <andrei@iptel.org>
Tue, 28 Apr 2009 10:44:38 +0000 (12:44 +0200)
(int)"" = 0
(int)"<number>" = <number>  (e.g. (int)"123" = 123)
(int)"<non-numeric>" = 0    (e.g. (int)"abc" = 0)

rvalue.c

index 259d921..e815c24 100644 (file)
--- 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;