[SR-Dev] git:master: core expr: new internal operators

Andrei Pelinescu-Onciul andrei at iptel.org
Fri Apr 24 21:52:44 CEST 2009


Module: sip-router
Branch: master
Commit: ea1babd9d9e6e90629ad4ad091b1ab90241332fd
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=ea1babd9d9e6e90629ad4ad091b1ab90241332fd

Author: Andrei Pelinescu-Onciul <andrei at iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei at iptel.org>
Date:   Fri Apr 24 14:45:36 2009 +0200

core expr:  new internal operators

- added RVE_STRLEN_OP, RVE_STREMPTY_OP and RVE_DEFINED_OP

---

 rvalue.c |  179 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 rvalue.h |    6 ++-
 2 files changed, 182 insertions(+), 3 deletions(-)

diff --git a/rvalue.c b/rvalue.c
index 8bd0aa2..74e8df5 100644
--- a/rvalue.c
+++ b/rvalue.c
@@ -23,6 +23,7 @@
  * History:
  * --------
  *  2008-12-01  initial version (andrei)
+ *  2009-04-24  added support for defined, strempty, strlen (andrei)
  */
 
 #include "rvalue.h"
@@ -390,6 +391,9 @@ enum rval_type rve_guess_type( struct rval_expr* rve)
 		case RVE_EQ_OP:
 		case RVE_DIFF_OP:
 		case RVE_IPLUS_OP:
+		case RVE_STRLEN_OP:
+		case RVE_STREMPTY_OP:
+		case RVE_DEFINED_OP:
 			return RV_INT;
 		case RVE_PLUS_OP:
 			/* '+' evaluates to the type of the left operand */
@@ -429,6 +433,9 @@ int rve_is_constant(struct rval_expr* rve)
 		case RVE_UMINUS_OP:
 		case RVE_BOOL_OP:
 		case RVE_LNOT_OP:
+		case RVE_STRLEN_OP:
+		case RVE_STREMPTY_OP:
+		case RVE_DEFINED_OP:
 			return rve_is_constant(rve->left.rve);
 		case RVE_MINUS_OP:
 		case RVE_MUL_OP:
@@ -478,6 +485,9 @@ static int rve_op_unary(enum rval_expr_op op)
 		case RVE_UMINUS_OP:
 		case RVE_BOOL_OP:
 		case RVE_LNOT_OP:
+		case RVE_STRLEN_OP:
+		case RVE_STREMPTY_OP:
+		case RVE_DEFINED_OP:
 			return 1;
 		case RVE_MINUS_OP:
 		case RVE_MUL_OP:
@@ -610,6 +620,7 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve,
 					return 1;
 				}
 			}
+			break;
 		case RVE_CONCAT_OP:
 			*type=RV_STR;
 			if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
@@ -632,6 +643,21 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve,
 					return 1;
 				}
 			}
+			break;
+		case RVE_STRLEN_OP:
+		case RVE_STREMPTY_OP:
+		case RVE_DEFINED_OP:
+			*type=RV_INT;
+			if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
+				if (type1==RV_INT){
+					if (bad_rve) *bad_rve=rve->left.rve;
+					if (bad_t) *bad_t=type1;
+					if (exp_t) *exp_t=RV_STR;
+					return 0;
+				}
+				return 1;
+			}
+			break;
 		case RVE_NONE_OP:
 			break;
 	}
@@ -974,7 +1000,7 @@ inline static int int_intop1(int* res, enum rval_expr_op op, int v)
 
 
 
-/** integer operation: *res= op v.
+/** integer operation: *res= v1 op v2
   * @return 0 on succes, \<0 on error
   */
 inline static int int_intop2(int* res, enum rval_expr_op op, int v1, int v2)
@@ -1054,6 +1080,27 @@ inline static int bool_strop2( enum rval_expr_op op, int* res,
 
 
 
+/** integer returning operation on string: *res= op str (returns integer)
+  * @return 0 on succes, \<0 on error
+  */
+inline static int int_strop1(int* res, enum rval_expr_op op, str* s1)
+{
+	switch(op){
+		case RVE_STRLEN_OP:
+			*res=s1->len;
+			break;
+		case RVE_STREMPTY_OP:
+			*res=(s1->len==0);
+			break;
+		default:
+			BUG("rv unsupported int_strop1 %d\n", op);
+			return -1;
+	}
+	return 0;
+}
+
+
+
 /** integer operation: ret= op v (returns a rvalue).
  * @return rvalue on success, 0 on error
  */
@@ -1306,6 +1353,107 @@ error:
 
 
 
+/** integer operation on rval evaluated as string.
+ * Can use cached rvalues (c1 & c2).
+ * @return 0 success, -1 on error
+ */
+inline static int rval_int_strop1(struct run_act_ctx* h,
+						 struct sip_msg* msg,
+						 int* res,
+						 enum rval_expr_op op,
+						 struct rvalue* l,
+						 struct rval_cache* c1)
+{
+	struct rvalue* rv1;
+	int ret;
+	
+	rv1=0;
+	ret=0;
+	if ((rv1=rval_convert(h, msg, RV_STR, l, c1))==0)
+		goto error;
+	ret=int_strop1(res, op, &rv1->v.s);
+	rval_destroy(rv1); 
+	return ret;
+error:
+	rval_destroy(rv1); 
+	return 0;
+}
+
+
+
+/** checks if rv is defined.
+ * @return 1 defined, 0 not defined, -1 on error
+ * Can use cached rvalues (c1).
+ * Note: a rv can be undefined if it's an undefined avp or pvar or
+ * if it's NONE
+ */
+inline static int rv_defined(struct run_act_ctx* h,
+						 struct sip_msg* msg,
+						 struct rvalue* rv, struct rval_cache* cache)
+{
+	avp_t* r_avp;
+	int_str avp_val;
+	pv_value_t pval;
+	int ret;
+	
+	ret=1;
+	switch(rv->type){
+		case RV_AVP:
+			if (unlikely(cache && cache->cache_type==RV_CACHE_AVP)){
+				if (cache->val_type==RV_NONE)
+					ret=0;
+			}else{
+				r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
+											&avp_val, rv->v.avps.index);
+				if (unlikely(r_avp==0)){
+					ret=0;
+				}
+			}
+			break;
+		case RV_PVAR:
+			/* PV_VAL_NULL or pv_get_spec_value error => undef */
+			if (unlikely(cache && cache->cache_type==RV_CACHE_PVAR)){
+				if (cache->val_type==RV_NONE)
+					ret=0;
+			}else{
+				memset(&pval, 0, sizeof(pval));
+				if (likely(pv_get_spec_value(msg, &rv->v.pvs, &pval)==0)){
+					if ((pval.flags & PV_VAL_NULL) &&
+							! (pval.flags & (PV_VAL_INT|PV_VAL_STR))){
+						ret=0;
+					}
+					pv_value_destroy(&pval);
+				}else{
+					ret=0; /* in case of error, consider it undef */
+				}
+			}
+			break;
+		case RV_NONE:
+			ret=0;
+			break;
+		default:
+			break;
+	}
+	return 1; /* defined */
+}
+
+
+/** defined (integer) operation on rve.
+ * @return 1 defined, 0 not defined, -1 on error
+ */
+inline static int int_rve_defined(struct run_act_ctx* h,
+						 struct sip_msg* msg,
+						 struct rval_expr* rve)
+{
+	/* only a rval can be undefined, any expression consisting on more
+	   then one rval => defined */
+	if (likely(rve->op==RVE_RVAL_OP))
+		return rv_defined(h, msg, &rve->left.rval, 0);
+	return 1;
+}
+
+
+
 /** evals an integer expr  to an int.
  * 
  *  *res=(int)eval(rve)
@@ -1431,6 +1579,18 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
 			*res=0;
 			ret=-1;
 			break;
+		case RVE_DEFINED_OP:
+			ret=int_rve_defined(h, msg, rve->left.rve);
+			break;
+		case RVE_STRLEN_OP:
+		case RVE_STREMPTY_OP:
+			if (unlikely((rv1=rval_expr_eval(h, msg, rve->left.rve))==0)){
+					ret=-1;
+					break;
+			}
+			ret=rval_int_strop1(h, msg, res, rve->op, rv1, 0);
+			rval_destroy(rv1);
+			break;
 		case RVE_NONE_OP:
 		/*default:*/
 			BUG("invalid rval int expression operation %d\n", rve->op);
@@ -1503,6 +1663,9 @@ int rval_expr_eval_rvint(			   struct run_act_ctx* h,
 		case RVE_EQ_OP:
 		case RVE_DIFF_OP:
 		case RVE_IPLUS_OP:
+		case RVE_STRLEN_OP:
+		case RVE_STREMPTY_OP:
+		case RVE_DEFINED_OP:
 			/* operator forces integer type */
 			ret=rval_expr_eval_int(h, msg, res_i, rve);
 			*res_rv=0;
@@ -1560,7 +1723,7 @@ error:
  * WARNING: result must be rval_destroy()'ed if non-null (it might be
  * a reference to another rval). The result can be modified only
  * if rv_chg_in_place() returns true.
- * @result rvalue on success, 0 on error
+ * @return rvalue on success, 0 on error
  */
 struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg,
 								struct rval_expr* rve)
@@ -1598,6 +1761,9 @@ struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg,
 		case RVE_EQ_OP:
 		case RVE_DIFF_OP:
 		case RVE_IPLUS_OP:
+		case RVE_STRLEN_OP:
+		case RVE_STREMPTY_OP:
+		case RVE_DEFINED_OP:
 			/* operator forces integer type */
 			r=rval_expr_eval_int(h, msg, &i, rve);
 			if (likely(r==0)){
@@ -1800,6 +1966,9 @@ struct rval_expr* mk_rval_expr1(enum rval_expr_op op, struct rval_expr* rve1,
 		case RVE_UMINUS_OP:
 		case RVE_BOOL_OP:
 		case RVE_LNOT_OP:
+		case RVE_STRLEN_OP:
+		case RVE_STREMPTY_OP:
+		case RVE_DEFINED_OP:
 			break;
 		default:
 			BUG("unsupported unary operator %d\n", op);
@@ -1874,6 +2043,9 @@ static int rve_op_is_assoc(enum rval_expr_op op)
 		case RVE_UMINUS_OP:
 		case RVE_BOOL_OP:
 		case RVE_LNOT_OP:
+		case RVE_STRLEN_OP:
+		case RVE_STREMPTY_OP:
+		case RVE_DEFINED_OP:
 			/* one operand expression => cannot be assoc. */
 			return 0;
 		case RVE_DIV_OP:
@@ -1911,6 +2083,9 @@ static int rve_op_is_commutative(enum rval_expr_op op, enum rval_type type)
 		case RVE_UMINUS_OP:
 		case RVE_BOOL_OP:
 		case RVE_LNOT_OP:
+		case RVE_STRLEN_OP:
+		case RVE_STREMPTY_OP:
+		case RVE_DEFINED_OP:
 			/* one operand expression => cannot be commut. */
 			return 0;
 		case RVE_DIV_OP:
diff --git a/rvalue.h b/rvalue.h
index 88fd6f2..a9dbe0d 100644
--- a/rvalue.h
+++ b/rvalue.h
@@ -64,8 +64,12 @@ enum rval_expr_op{
 	RVE_PLUS_OP,  /* generic plus (int or str) returns left + right */
 	RVE_EQ_OP,    /*  2 members, returns left == right  (int)*/
 	RVE_DIFF_OP,  /*  2 members, returns left != right  (int)*/
-	RVE_CONCAT_OP,/* string concatenation, returns left . right */
 	/* str only */
+	RVE_CONCAT_OP,/* 2 members, string concat, returns left . right (str)*/
+	RVE_STRLEN_OP, /* one member, string length:, returns strlen(val) (int)*/
+	RVE_STREMPTY_OP, /* one member, returns val=="" (bool) */
+	/* avp, pvars a.s.o */
+	RVE_DEFINED_OP, /* one member, returns is_defined(val) (bool) */
 };
 
 




More information about the sr-dev mailing list