Browse code

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)

Andrei Pelinescu-Onciul authored on 28/04/2009 10:00:04
Showing 1 changed files
... ...
@@ -24,6 +24,9 @@
24 24
  * --------
25 25
  *  2008-12-01  initial version (andrei)
26 26
  *  2009-04-24  added support for defined, strempty, strlen (andrei)
27
+ *  2009-04-28  int and str automatic conversions: (int)undef=0,
28
+ *               (str)undef="", (int)""=0, (int)"123"=123, (int)"abc"=0
29
+ *               (andrei)
27 30
  */
28 31
 
29 32
 #include "rvalue.h"
... ...
@@ -686,12 +689,19 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
686 686
 	avp_t* r_avp;
687 687
 	int_str avp_val;
688 688
 	pv_value_t pval;
689
+	str tmp;
690
+	str* s;
691
+	int r;
692
+	int destroy_pval;
689 693
 	
694
+	destroy_pval=0;
695
+	s=0;
690 696
 	switch(rv->type){
691 697
 		case RV_INT:
692 698
 			*i=rv->v.l;
693 699
 			break;
694 700
 		case RV_STR:
701
+			s=&rv->v.s;
695 702
 			goto rv_str;
696 703
 		case RV_BEXPR:
697 704
 			*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,
707 707
 				*i=0;
708 708
 			break;
709 709
 		case RV_SEL:
710
+			r=run_select(&tmp, &rv->v.sel, msg);
711
+			if (unlikely(r!=0)){
712
+				if (r<0)
713
+					goto eval_error;
714
+				else /* i>0  => undefined */
715
+					goto undef;
716
+			}
717
+			s=&tmp;
710 718
 			goto rv_str;
711 719
 		case RV_AVP:
712 720
 			if (unlikely(cache && cache->cache_type==RV_CACHE_AVP)){
713 721
 				if (likely(cache->val_type==RV_INT)){
714 722
 					*i=cache->c.avp_val.n;
715
-				}else if (cache->val_type==RV_STR)
723
+				}else if (cache->val_type==RV_STR){
724
+					s=&cache->c.avp_val.s;
716 725
 					goto rv_str;
717
-				else if (cache->val_type==RV_NONE)
726
+				}else if (cache->val_type==RV_NONE)
718 727
 					goto undef;
719 728
 				else goto error_cache;
720 729
 			}else{
... ...
@@ -722,6 +741,7 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
722 722
 											&avp_val, rv->v.avps.index);
723 723
 				if (likely(r_avp)){
724 724
 					if (unlikely(r_avp->flags & AVP_VAL_STR)){
725
+						s=&avp_val.s;
725 726
 						goto rv_str;
726 727
 					}else{
727 728
 						*i=avp_val.n;
... ...
@@ -736,9 +756,10 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
736 736
 				if (likely((cache->val_type==RV_INT) || 
737 737
 								(cache->c.pval.flags & PV_VAL_INT))){
738 738
 					*i=cache->c.pval.ri;
739
-				}else if (cache->val_type==RV_STR)
739
+				}else if (cache->val_type==RV_STR){
740
+					s=&cache->c.pval.rs;
740 741
 					goto rv_str;
741
-				else if (cache->val_type==RV_NONE)
742
+				}else if (cache->val_type==RV_NONE)
742 743
 					goto undef;
743 744
 				else goto error_cache;
744 745
 			}else{
... ...
@@ -748,7 +769,8 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
748 748
 						*i=pval.ri;
749 749
 						pv_value_destroy(&pval);
750 750
 					}else if (likely(pval.flags & PV_VAL_STR)){
751
-						pv_value_destroy(&pval);
751
+						destroy_pval=1; /* we must pv_value_destroy() later*/
752
+						s=&pval.rs;
752 753
 						goto rv_str;
753 754
 					}else{
754 755
 						/* no PV_VAL_STR and no PV_VAL_INT => undef
... ...
@@ -775,8 +797,16 @@ error_cache:
775 775
 	BUG("invalid cached value:cache type %d, value type %d\n",
776 776
 			cache?cache->cache_type:0, cache?cache->val_type:0);
777 777
 rv_str:
778
-	/* rv is of string type => error */
779
-	/* ERR("string in int expression\n"); */
778
+	/* rv is of string type => try to convert it to int */
779
+	/* if "" => 0 (most likely case) */
780
+	if (likely(s->len==0)) *i=0;
781
+	else if (unlikely(str2sint(s, i)!=0)){
782
+		/* error converting to int => non numeric => 0 */
783
+		*i=0;
784
+	}
785
+	if (destroy_pval)
786
+		pv_value_destroy(&pval);
787
+	return 0;
780 788
 error:
781 789
 	*i=0;
782 790
 	return -1;