Browse code

core expr eval: undef conversion to int and str

(int)(undef)=0
(str)(undef)=""

Andrei Pelinescu-Onciul authored on 28/04/2009 08:50:56
Showing 1 changed files
... ...
@@ -668,6 +668,15 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve,
668 668
 
669 669
 /** get the integer value of an rvalue.
670 670
   * *i=(int)rv
671
+  * if rv == undefined select, avp or pvar, return 0.
672
+  * if an error occurs while evaluating a select, avp or pvar, behave as
673
+  * for the undefined case (and return success).
674
+  * @param h - script context handle
675
+  * @param msg - sip msg
676
+  * @param i   - pointer to int, where the conversion result will be stored
677
+  * @param rv   - rvalue to be converted
678
+  * @param cache - cached rv value (read-only), can be 0
679
+  *
671 680
   * @return 0 on success, \<0 on error and EXPR_DROP on drop
672 681
  */
673 682
 int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
... ...
@@ -705,7 +714,9 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
705 705
 					*i=cache->c.avp_val.n;
706 706
 				}else if (cache->val_type==RV_STR)
707 707
 					goto rv_str;
708
-				else goto error;
708
+				else if (cache->val_type==RV_NONE)
709
+					goto undef;
710
+				else goto error_cache;
709 711
 			}else{
710 712
 				r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
711 713
 											&avp_val, rv->v.avps.index);
... ...
@@ -716,7 +727,7 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
716 716
 						*i=avp_val.n;
717 717
 					}
718 718
 				}else{
719
-					goto error;
719
+					goto undef;
720 720
 				}
721 721
 			}
722 722
 			break;
... ...
@@ -727,7 +738,9 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
727 727
 					*i=cache->c.pval.ri;
728 728
 				}else if (cache->val_type==RV_STR)
729 729
 					goto rv_str;
730
-				else goto error;
730
+				else if (cache->val_type==RV_NONE)
731
+					goto undef;
732
+				else goto error_cache;
731 733
 			}else{
732 734
 				memset(&pval, 0, sizeof(pval));
733 735
 				if (likely(pv_get_spec_value(msg, &rv->v.pvs, &pval)==0)){
... ...
@@ -738,11 +751,13 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
738 738
 						pv_value_destroy(&pval);
739 739
 						goto rv_str;
740 740
 					}else{
741
+						/* no PV_VAL_STR and no PV_VAL_INT => undef
742
+						   (PV_VAL_NULL) */
741 743
 						pv_value_destroy(&pval);
742
-						goto error;
744
+						goto undef;
743 745
 					}
744 746
 				}else{
745
-					goto error;
747
+					goto eval_error;
746 748
 				}
747 749
 			}
748 750
 			break;
... ...
@@ -751,10 +766,19 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
751 751
 			goto error;
752 752
 	}
753 753
 	return 0;
754
+undef:
755
+eval_error: /* same as undefined */
756
+	/* handle undefined => result 0, return success */
757
+	*i=0;
758
+	return 0;
759
+error_cache:
760
+	BUG("invalid cached value:cache type %d, value type %d\n",
761
+			cache?cache->cache_type:0, cache?cache->val_type:0);
754 762
 rv_str:
755 763
 	/* rv is of string type => error */
756 764
 	/* ERR("string in int expression\n"); */
757 765
 error:
766
+	*i=0;
758 767
 	return -1;
759 768
 }
760 769
 
... ...
@@ -762,6 +786,9 @@ error:
762 762
 
763 763
 /** get the string value of an rv in a tmp variable
764 764
   * *s=(str)rv
765
+  * if rv == undefined select, avp or pvar, return "".
766
+  * if an error occurs while evaluating a select, avp or pvar, behave as
767
+  * for the undefined case (and return success).
765 768
   * The result points either to a temporary string or inside
766 769
   * new_cache. new_cache must be non zero, initialized previously,
767 770
   * and it _must_ be rval_cache_clean(...)'ed when done.
... ...
@@ -771,9 +798,9 @@ error:
771 771
   * @param h - script context handle
772 772
   * @param msg - sip msg
773 773
   * @param tmpv - str return value (pointer to a str struct that will be
774
-  *               be filled.
774
+  *               be filled with the conversion result)
775 775
   * @param rv   - rvalue to be converted
776
-  * @param cache - cached rv value (read-only)
776
+  * @param cache - cached rv value (read-only), can be 0
777 777
   * @param tmp_cache - used for temporary storage (so that tmpv will not
778 778
   *                 point to possible freed data), it must be non-null,
779 779
   *                 initialized and cleaned afterwards.
... ...
@@ -814,10 +841,9 @@ int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg,
814 814
 			i=run_select(tmpv, &rv->v.sel, msg);
815 815
 			if (unlikely(i!=0)){
816 816
 				if (i<0){
817
-					goto error;
818
-				}else { /* i>0 */
819
-					tmpv->s="";
820
-					tmpv->len=0;
817
+					goto eval_error;
818
+				}else { /* i>0  => undefined */
819
+					goto undef;
821 820
 				}
822 821
 			}
823 822
 			break;
... ...
@@ -828,7 +854,9 @@ int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg,
828 828
 				}else if (cache->val_type==RV_INT){
829 829
 					i=cache->c.avp_val.n;
830 830
 					tmpv->s=int2str(i, &tmpv->len);
831
-				}else goto error;
831
+				}else if (cache->val_type==RV_NONE){
832
+					goto undef;
833
+				}else goto error_cache;
832 834
 			}else{
833 835
 				r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
834 836
 											&tmp_cache->c.avp_val,
... ...
@@ -842,9 +870,7 @@ int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg,
842 842
 						i=tmp_cache->c.avp_val.n;
843 843
 						tmpv->s=int2str(i, &tmpv->len);
844 844
 					}
845
-				}else{
846
-					goto error;
847
-				}
845
+				}else goto undef;
848 846
 			}
849 847
 			break;
850 848
 		case RV_PVAR:
... ...
@@ -854,7 +880,9 @@ int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg,
854 854
 				}else if (cache->val_type==RV_INT){
855 855
 					i=cache->c.pval.ri;
856 856
 					tmpv->s=int2str(i, &tmpv->len);
857
-				}else goto error;
857
+				}else if (cache->val_type==RV_NONE){
858
+					goto undef;
859
+				}else goto error_cache;
858 860
 			}else{
859 861
 				memset(&tmp_cache->c.pval, 0, sizeof(tmp_cache->c.pval));
860 862
 				if (likely(pv_get_spec_value(msg, &rv->v.pvs,
... ...
@@ -871,11 +899,13 @@ int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg,
871 871
 						pv_value_destroy(&tmp_cache->c.pval);
872 872
 						tmpv->s=int2str(i, &tmpv->len);
873 873
 					}else{
874
+						/* no PV_VAL_STR and no PV_VAL_INT => undef
875
+						   (PV_VAL_NULL) */
874 876
 						pv_value_destroy(&tmp_cache->c.pval);
875
-						goto error;
877
+						goto undef;
876 878
 					}
877 879
 				}else{
878
-					goto error;
880
+					goto eval_error;
879 881
 				}
880 882
 			}
881 883
 			break;
... ...
@@ -884,7 +914,18 @@ int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg,
884 884
 			goto error;
885 885
 	}
886 886
 	return 0;
887
+undef:
888
+eval_error: /* same as undefined */
889
+	/* handle undefined => result "", return success */
890
+	tmpv->s="";
891
+	tmpv->len=0;
892
+	return 0;
893
+error_cache:
894
+	BUG("invalid cached value:cache type %d, value type %d\n",
895
+			cache?cache->cache_type:0, cache?cache->val_type:0);
887 896
 error:
897
+	tmpv->s="";
898
+	tmpv->len=0;
888 899
 	return -1;
889 900
 }
890 901