Module: sip-router Branch: master Commit: 0b3019f699dfb999be04572d4c35a613b6032435 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=0b3019f6...
Author: Andrei Pelinescu-Onciul andrei@iptel.org Committer: Andrei Pelinescu-Onciul andrei@iptel.org Date: Tue May 5 13:51:40 2009 +0200
core expr. eval: support for int & str casts
- new internal operators for force-casting to int or str - fix int conversion failure for v1 str_concat v2
---
rvalue.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++----------- rvalue.h | 3 ++ 2 files changed, 92 insertions(+), 19 deletions(-)
diff --git a/rvalue.c b/rvalue.c index c332173..db30fda 100644 --- a/rvalue.c +++ b/rvalue.c @@ -28,6 +28,7 @@ * (str)undef="", (int)""=0, (int)"123"=123, (int)"abc"=0 * handle undef == expr, in function of the UNDEF_EQ_* defines. * (andrei) + * 2009-05-05 casts operator for int & string (andrei) */
/* special defines: @@ -480,11 +481,13 @@ enum rval_type rve_guess_type( struct rval_expr* rve) case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: + case RVE_INT_OP: return RV_INT; case RVE_PLUS_OP: /* '+' evaluates to the type of the left operand */ return rve_guess_type(rve->left.rve); case RVE_CONCAT_OP: + case RVE_STR_OP: return RV_STR; case RVE_NONE_OP: break; @@ -522,6 +525,8 @@ int rve_is_constant(struct rval_expr* rve) case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: + case RVE_INT_OP: + case RVE_STR_OP: return rve_is_constant(rve->left.rve); case RVE_MINUS_OP: case RVE_MUL_OP: @@ -579,6 +584,8 @@ static int rve_op_unary(enum rval_expr_op op) case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: + case RVE_INT_OP: + case RVE_STR_OP: return 1; case RVE_MINUS_OP: case RVE_MUL_OP: @@ -781,6 +788,14 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve, return 1; } break; + case RVE_INT_OP: + *type=RV_INT; + return 1; + break; + case RVE_STR_OP: + *type=RV_STR; + return 1; + break; case RVE_NONE_OP: default: BUG("unexpected rve op %d\n", rve->op); @@ -1726,6 +1741,9 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg, break; ret=int_intop1(res, rve->op, i1); break; + case RVE_INT_OP: + ret=rval_expr_eval_int(h, msg, res, rve->left.rve); + break; case RVE_MUL_OP: case RVE_DIV_OP: case RVE_MINUS_OP: @@ -1857,27 +1875,49 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg, } } break; -#if 0 - case RVE_MATCH_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(res, rve->op, rv1, 0, rv2, 0); + case RVE_CONCAT_OP: + /* eval expression => string */ + if (unlikely((rv1=rval_expr_eval(h, msg, rve))==0)){ + ret=-1; + break; + } + /* conver to int */ + ret=rval_get_int(h, msg, res, rv1, 0); /* convert to int */ + rval_destroy(rv1); + break; + case RVE_STR_OP: + /* (str)expr => eval expression */ + rval_cache_init(&c1); + if (unlikely((ret=rval_expr_eval_rvint(h, msg, &rv1, res, + rve->left.rve, &c1))<0)){ + /* error */ + rval_cache_clean(&c1); + break; + } + if (unlikely(rv1)){ + /* expr evaluated to string => (int)(str)v == (int)v */ + ret=rval_get_int(h, msg, res, rv1, &c1); /* convert to int */ rval_destroy(rv1); - rval_destroy(rv2); + rval_cache_clean(&c1); + } /* else (rv1==0) + => expr evaluated to int => + return (int)(str)v == (int)v => do nothing */ break; -#endif - case RVE_CONCAT_OP: - *res=0; - ret=-1; + +#if 0 + /* same thing as above, but in a not optimized, easier to + understand way */ + /* 1. (str) expr => eval expr */ + if (unlikely((rv1=rval_expr_eval(h, msg, rve->left.rve))==0)){ + ret=-1; + break; + } + /* 2. convert to str and then convert to int + but since (int)(str)v == (int)v skip over (str)v */ + ret=rval_get_int(h, msg, res, rv1, 0); /* convert to int */ + rval_destroy(rv1); break; +#endif case RVE_DEFINED_OP: ret=int_rve_defined(h, msg, res, rve->left.rve); break; @@ -1918,8 +1958,19 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
/** evals a rval expr. into an int or another rv(str). * WARNING: rv result (rv_res) must be rval_destroy()'ed if non-null - * (it might be a reference to another rval). The result can be + * (it might be a reference to another rval). The result can be * modified only if rv_chg_in_place() returns true. + * @param res_rv - pointer to rvalue result, if non-null it means the + * expression evaluated to a non-int (str), which will be + * stored here. + * @param res_i - pointer to int result, if res_rv==0 and the function + * returns success => the result is an int which will be + * stored here. + * @param rve - expression that will be evaluated. + * @param cache - write-only value cache, it might be filled if non-null and + * empty (rval_cache_init()). If non-null, it _must_ be + * rval_cache_clean()'ed when done. + * * @result 0 on success, -1 on error, sets *res_rv or *res_i. */ int rval_expr_eval_rvint( struct run_act_ctx* h, @@ -1986,6 +2037,7 @@ int rval_expr_eval_rvint( struct run_act_ctx* h, case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: + case RVE_INT_OP: /* operator forces integer type */ ret=rval_expr_eval_int(h, msg, res_i, rve); *res_rv=0; @@ -2020,6 +2072,7 @@ int rval_expr_eval_rvint( struct run_act_ctx* h, rval_cache_clean(&c1); break; case RVE_CONCAT_OP: + case RVE_STR_OP: *res_rv=rval_expr_eval(h, msg, rve); ret=-(*res_rv==0); break; @@ -2089,6 +2142,7 @@ struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg, case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: + case RVE_INT_OP: /* operator forces integer type */ r=rval_expr_eval_int(h, msg, &i, rve); if (likely(r==0)){ @@ -2168,6 +2222,14 @@ struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg, } ret=rval_str_add2(h, msg, rv1, 0, rv2, 0); break; + case RVE_STR_OP: + rv1=rval_expr_eval(h, msg, rve->left.rve); + if (unlikely(rv1==0)){ + ERR("rval expression evaluation failed\n"); + goto error; + } + ret=rval_convert(h, msg, RV_STR, rv1, 0); + break; case RVE_NONE_OP: /*default:*/ BUG("invalid rval expression operation %d\n", rve->op); @@ -2292,6 +2354,8 @@ struct rval_expr* mk_rval_expr1(enum rval_expr_op op, struct rval_expr* rve1, case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: + case RVE_INT_OP: + case RVE_STR_OP: break; default: BUG("unsupported unary operator %d\n", op); @@ -2374,6 +2438,8 @@ static int rve_op_is_assoc(enum rval_expr_op op) case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: + case RVE_INT_OP: + case RVE_STR_OP: /* one operand expression => cannot be assoc. */ return 0; case RVE_DIV_OP: @@ -2422,6 +2488,8 @@ static int rve_op_is_commutative(enum rval_expr_op op) case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: + case RVE_INT_OP: + case RVE_STR_OP: /* one operand expression => cannot be commut. */ return 0; case RVE_DIV_OP: @@ -3291,6 +3359,8 @@ int fix_rval_expr(void** p) case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: + case RVE_INT_OP: + case RVE_STR_OP: ret=fix_rval_expr((void**)&rve->left.rve); if (ret<0) return ret; break; diff --git a/rvalue.h b/rvalue.h index c48d1e8..652c902 100644 --- a/rvalue.h +++ b/rvalue.h @@ -25,6 +25,7 @@ * 2008-11-30 initial version (andrei) * 2009-04-28 added string and interger versions for the EQ and DIFF * operators (andrei) + * 2009-05-05 casts operator for int & string (andrei) */
#ifndef _rvalue_h_ @@ -77,6 +78,8 @@ enum rval_expr_op{ RVE_MATCH_OP, /* 2 members, string ~), returns left matches re(right) */ /* avp, pvars a.s.o */ RVE_DEFINED_OP, /* one member, returns is_defined(val) (bool) */ + RVE_INT_OP, /* one member, returns (int)val (int) */ + RVE_STR_OP /* one member, returns (str)val (str) */ };