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 689
 	avp_t* r_avp;
687 690
 	int_str avp_val;
688 691
 	pv_value_t pval;
692
+	str tmp;
693
+	str* s;
694
+	int r;
695
+	int destroy_pval;
689 696
 	
697
+	destroy_pval=0;
698
+	s=0;
690 699
 	switch(rv->type){
691 700
 		case RV_INT:
692 701
 			*i=rv->v.l;
693 702
 			break;
694 703
 		case RV_STR:
704
+			s=&rv->v.s;
695 705
 			goto rv_str;
696 706
 		case RV_BEXPR:
697 707
 			*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 717
 				*i=0;
708 718
 			break;
709 719
 		case RV_SEL:
720
+			r=run_select(&tmp, &rv->v.sel, msg);
721
+			if (unlikely(r!=0)){
722
+				if (r<0)
723
+					goto eval_error;
724
+				else /* i>0  => undefined */
725
+					goto undef;
726
+			}
727
+			s=&tmp;
710 728
 			goto rv_str;
711 729
 		case RV_AVP:
712 730
 			if (unlikely(cache && cache->cache_type==RV_CACHE_AVP)){
713 731
 				if (likely(cache->val_type==RV_INT)){
714 732
 					*i=cache->c.avp_val.n;
715
-				}else if (cache->val_type==RV_STR)
733
+				}else if (cache->val_type==RV_STR){
734
+					s=&cache->c.avp_val.s;
716 735
 					goto rv_str;
717
-				else if (cache->val_type==RV_NONE)
736
+				}else if (cache->val_type==RV_NONE)
718 737
 					goto undef;
719 738
 				else goto error_cache;
720 739
 			}else{
... ...
@@ -722,6 +741,7 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
722 741
 											&avp_val, rv->v.avps.index);
723 742
 				if (likely(r_avp)){
724 743
 					if (unlikely(r_avp->flags & AVP_VAL_STR)){
744
+						s=&avp_val.s;
725 745
 						goto rv_str;
726 746
 					}else{
727 747
 						*i=avp_val.n;
... ...
@@ -736,9 +756,10 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
736 756
 				if (likely((cache->val_type==RV_INT) || 
737 757
 								(cache->c.pval.flags & PV_VAL_INT))){
738 758
 					*i=cache->c.pval.ri;
739
-				}else if (cache->val_type==RV_STR)
759
+				}else if (cache->val_type==RV_STR){
760
+					s=&cache->c.pval.rs;
740 761
 					goto rv_str;
741
-				else if (cache->val_type==RV_NONE)
762
+				}else if (cache->val_type==RV_NONE)
742 763
 					goto undef;
743 764
 				else goto error_cache;
744 765
 			}else{
... ...
@@ -748,7 +769,8 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
748 769
 						*i=pval.ri;
749 770
 						pv_value_destroy(&pval);
750 771
 					}else if (likely(pval.flags & PV_VAL_STR)){
751
-						pv_value_destroy(&pval);
772
+						destroy_pval=1; /* we must pv_value_destroy() later*/
773
+						s=&pval.rs;
752 774
 						goto rv_str;
753 775
 					}else{
754 776
 						/* no PV_VAL_STR and no PV_VAL_INT => undef
... ...
@@ -775,8 +797,16 @@ error_cache:
775 797
 	BUG("invalid cached value:cache type %d, value type %d\n",
776 798
 			cache?cache->cache_type:0, cache?cache->val_type:0);
777 799
 rv_str:
778
-	/* rv is of string type => error */
779
-	/* ERR("string in int expression\n"); */
800
+	/* rv is of string type => try to convert it to int */
801
+	/* if "" => 0 (most likely case) */
802
+	if (likely(s->len==0)) *i=0;
803
+	else if (unlikely(str2sint(s, i)!=0)){
804
+		/* error converting to int => non numeric => 0 */
805
+		*i=0;
806
+	}
807
+	if (destroy_pval)
808
+		pv_value_destroy(&pval);
809
+	return 0;
780 810
 error:
781 811
 	*i=0;
782 812
 	return -1;