Module: sip-router Branch: andrei/type_conversion Commit: 783ad9b3e0ebdee05a8e1f710c0e14da777c9ada URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=783ad9b3...
Author: Andrei Pelinescu-Onciul andrei@iptel.org Committer: Andrei Pelinescu-Onciul andrei@iptel.org Date: Tue Apr 28 17:39:35 2009 +0200
core expr eval: internal == & != int and str only versions
- added RVE_IEQ_OP and RVE_IDIFF_OP - internal integer only (force argument conversion to int) operators - added RVE_STREQ and RVE_STRDIFF_OP - internal string only (force argument conversion to str) operators
---
rvalue.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- rvalue.h | 6 +++ 2 files changed, 108 insertions(+), 9 deletions(-)
diff --git a/rvalue.c b/rvalue.c index 2961ee9..36c6ef4 100644 --- a/rvalue.c +++ b/rvalue.c @@ -38,7 +38,7 @@ * UNDEF_EQ_UNDEF_TRUE : undef == something false except for undef==undef * which is true * no UNDEF_EQ* define : undef == expr => convert undef to typeof(expr) - * and perorm normal ==. undef == undef will be + * and perform normal ==. undef == undef will be * converted to string and it will be true * ("" == "") * NOTE: expr == undef, with defined(expr) is always evaluated this way: @@ -411,6 +411,10 @@ enum rval_type rve_guess_type( struct rval_expr* rve) case RVE_LTE_OP: case RVE_EQ_OP: case RVE_DIFF_OP: + case RVE_IEQ_OP: + case RVE_IDIFF_OP: + case RVE_STREQ_OP: + case RVE_STRDIFF_OP: case RVE_IPLUS_OP: case RVE_STRLEN_OP: case RVE_STREMPTY_OP: @@ -471,6 +475,10 @@ int rve_is_constant(struct rval_expr* rve) case RVE_LTE_OP: case RVE_EQ_OP: case RVE_DIFF_OP: + case RVE_IEQ_OP: + case RVE_IDIFF_OP: + case RVE_STREQ_OP: + case RVE_STRDIFF_OP: case RVE_PLUS_OP: case RVE_IPLUS_OP: case RVE_CONCAT_OP: @@ -523,6 +531,10 @@ static int rve_op_unary(enum rval_expr_op op) case RVE_LTE_OP: case RVE_EQ_OP: case RVE_DIFF_OP: + case RVE_IEQ_OP: + case RVE_IDIFF_OP: + case RVE_STREQ_OP: + case RVE_STRDIFF_OP: case RVE_PLUS_OP: case RVE_IPLUS_OP: case RVE_CONCAT_OP: @@ -585,6 +597,8 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve, case RVE_GTE_OP: case RVE_LT_OP: case RVE_LTE_OP: + case RVE_IEQ_OP: + case RVE_IDIFF_OP: case RVE_IPLUS_OP: *type=RV_INT; if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){ @@ -665,6 +679,30 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve, } } break; + case RVE_STREQ_OP: + case RVE_STRDIFF_OP: + *type=RV_INT; + if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){ + if (rve_check_type(&type2, rve->right.rve, bad_rve, bad_t, + exp_t)){ + if ((type2!=type1) && (type1!=RV_NONE) && + (type2!=RV_NONE) && + !(type1==RV_STR && type2==RV_INT)){ + if (bad_rve) *bad_rve=rve->right.rve; + if (bad_t) *bad_t=type2; + if (exp_t) *exp_t=type1; + return 0; + } + 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_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: @@ -1136,9 +1174,11 @@ inline static int int_intop2(int* res, enum rval_expr_op op, int v1, int v2) *res=v1 <= v2; break; case RVE_EQ_OP: + case RVE_IEQ_OP: *res=v1 == v2; break; case RVE_DIFF_OP: + case RVE_IDIFF_OP: *res=v1 != v2; break; case RVE_CONCAT_OP: @@ -1157,12 +1197,19 @@ inline static int int_intop2(int* res, enum rval_expr_op op, int v1, int v2) inline static int bool_strop2( enum rval_expr_op op, int* res, str* s1, str* s2) { - if (s1->len!=s2->len) - *res= op==RVE_DIFF_OP; - else if (memcmp(s1->s, s2->s, s1->len)==0) - *res= op==RVE_EQ_OP; - else - *res= op==RVE_DIFF_OP; + switch(op){ + case RVE_EQ_OP: + case RVE_STREQ_OP: + *res= (s1->len==s2->len) && (memcmp(s1->s, s2->s, s1->len)==0); + break; + case RVE_DIFF_OP: + case RVE_STRDIFF_OP: + *res= (s1->len!=s2->len) || (memcmp(s1->s, s2->s, s1->len)!=0); + break; + default: + BUG("rv unsupported intop %d\n", op); + return -1; + } return 0; }
@@ -1593,6 +1640,8 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg, case RVE_GTE_OP: case RVE_LT_OP: case RVE_LTE_OP: + case RVE_IEQ_OP: + case RVE_IDIFF_OP: if (unlikely( (ret=rval_expr_eval_int(h, msg, &i1, rve->left.rve)) <0) ) break; @@ -1735,6 +1784,21 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg, case RVE_DEFINED_OP: ret=int_rve_defined(h, msg, res, rve->left.rve); break; + case RVE_STREQ_OP: + case RVE_STRDIFF_OP: + if (unlikely((rv1=rval_expr_eval(h, msg, rve->left.rve))==0)){ + ret=-1; + break; + } + if (unlikely((rv2=rval_expr_eval(h, msg, rve->right.rve))==0)){ + rval_destroy(rv1); + ret=-1; + break; + } + ret=rval_str_lop2(h, msg, res, rve->op, rv1, 0, rv2, 0); + rval_destroy(rv1); + rval_destroy(rv2); + break; case RVE_STRLEN_OP: case RVE_STREMPTY_OP: if (unlikely((rv1=rval_expr_eval(h, msg, rve->left.rve))==0)){ @@ -1815,7 +1879,11 @@ int rval_expr_eval_rvint( struct run_act_ctx* h, case RVE_LTE_OP: case RVE_EQ_OP: case RVE_DIFF_OP: + case RVE_IEQ_OP: + case RVE_IDIFF_OP: case RVE_IPLUS_OP: + case RVE_STREQ_OP: + case RVE_STRDIFF_OP: case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: @@ -1913,7 +1981,11 @@ struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg, case RVE_LTE_OP: case RVE_EQ_OP: case RVE_DIFF_OP: + case RVE_IEQ_OP: + case RVE_IDIFF_OP: case RVE_IPLUS_OP: + case RVE_STREQ_OP: + case RVE_STRDIFF_OP: case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: @@ -2168,6 +2240,10 @@ struct rval_expr* mk_rval_expr2(enum rval_expr_op op, struct rval_expr* rve1, case RVE_IPLUS_OP: case RVE_EQ_OP: case RVE_DIFF_OP: + case RVE_IEQ_OP: + case RVE_IDIFF_OP: + case RVE_STREQ_OP: + case RVE_STRDIFF_OP: case RVE_CONCAT_OP: break; default: @@ -2220,6 +2296,10 @@ static int rve_op_is_assoc(enum rval_expr_op op) case RVE_LTE_OP: case RVE_EQ_OP: case RVE_DIFF_OP: + case RVE_IEQ_OP: + case RVE_IDIFF_OP: + case RVE_STREQ_OP: + case RVE_STRDIFF_OP: return 0; } return 0; @@ -2250,18 +2330,26 @@ static int rve_op_is_commutative(enum rval_expr_op op, enum rval_type type) case RVE_MUL_OP: case RVE_BAND_OP: case RVE_BOR_OP: - return 1; case RVE_LAND_OP: case RVE_LOR_OP: + case RVE_IEQ_OP: + case RVE_IDIFF_OP: + case RVE_STREQ_OP: + case RVE_STRDIFF_OP: return 1; case RVE_GT_OP: case RVE_GTE_OP: case RVE_LT_OP: case RVE_LTE_OP: case RVE_EQ_OP: + return 0; case RVE_DIFF_OP: case RVE_CONCAT_OP: - return 0; +#if !defined(UNDEF_EQ_ALWAYS_FALSE) && !defined(UNDEF_EQ_UNDEF_TRUE) + return 1; +#else + return 0 /* asymmetrical undef handling */; +#endif } return 0; } @@ -2633,6 +2721,7 @@ static int rve_opt_01(struct rval_expr* rve, enum rval_type rve_type) } break; case RVE_EQ_OP: + case RVE_STREQ_OP: if (rv->v.s.len==0){ /* $v == "" -> strempty($v) "" == $v -> strempty ($v) */ @@ -2973,6 +3062,10 @@ int fix_rval_expr(void** p) case RVE_IPLUS_OP: case RVE_EQ_OP: case RVE_DIFF_OP: + case RVE_IEQ_OP: + case RVE_IDIFF_OP: + case RVE_STREQ_OP: + case RVE_STRDIFF_OP: case RVE_CONCAT_OP: ret=fix_rval_expr((void**)&rve->left.rve); if (ret<0) return ret; diff --git a/rvalue.h b/rvalue.h index e99d1f8..f7fdcc1 100644 --- a/rvalue.h +++ b/rvalue.h @@ -23,6 +23,8 @@ * History: * -------- * 2008-11-30 initial version (andrei) + * 2009-04-28 added string and interger versions for the EQ and DIFF + * operators (andrei) */
#ifndef _rvalue_h_ @@ -59,6 +61,8 @@ enum rval_expr_op{ RVE_GTE_OP, /* 2 members, returns left >= right */ RVE_LT_OP, /* 2 members, returns left < right */ RVE_LTE_OP, /* 2 members, returns left <= right */ + RVE_IEQ_OP, /* 2 members, int == version, returns left == right */ + RVE_IDIFF_OP,/* 2 members, int != version, returns left != right */ RVE_IPLUS_OP, /* 2 members, integer +, returns int(a)+int(b) */ /* common int & str */ RVE_PLUS_OP, /* generic plus (int or str) returns left + right */ @@ -68,6 +72,8 @@ enum rval_expr_op{ 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) */ + RVE_STREQ_OP, /* 2 members, string == , returns left == right (bool)*/ + RVE_STRDIFF_OP,/* 2 members, string != , returns left != right (bool)*/ /* avp, pvars a.s.o */ RVE_DEFINED_OP, /* one member, returns is_defined(val) (bool) */ };