Module: sip-router
Branch: andrei/type_conversion
Commit: e9cb7f9402fc044eb877d2fea2dc59bac2c290a2
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=e9cb7f9…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Tue Apr 28 10:50:56 2009 +0200
core expr eval: undef conversion to int and str
(int)(undef)=0
(str)(undef)=""
---
rvalue.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++--------------
1 files changed, 59 insertions(+), 18 deletions(-)
diff --git a/rvalue.c b/rvalue.c
index aa99131..259d921 100644
--- a/rvalue.c
+++ b/rvalue.c
@@ -668,6 +668,15 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve,
/** get the integer value of an rvalue.
* *i=(int)rv
+ * if rv == undefined select, avp or pvar, return 0.
+ * if an error occurs while evaluating a select, avp or pvar, behave as
+ * for the undefined case (and return success).
+ * @param h - script context handle
+ * @param msg - sip msg
+ * @param i - pointer to int, where the conversion result will be stored
+ * @param rv - rvalue to be converted
+ * @param cache - cached rv value (read-only), can be 0
+ *
* @return 0 on success, \<0 on error and EXPR_DROP on drop
*/
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,
*i=cache->c.avp_val.n;
}else if (cache->val_type==RV_STR)
goto rv_str;
- else goto error;
+ else if (cache->val_type==RV_NONE)
+ goto undef;
+ else goto error_cache;
}else{
r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
&avp_val, rv->v.avps.index);
@@ -716,7 +727,7 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
*i=avp_val.n;
}
}else{
- goto error;
+ goto undef;
}
}
break;
@@ -727,7 +738,9 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
*i=cache->c.pval.ri;
}else if (cache->val_type==RV_STR)
goto rv_str;
- else goto error;
+ else if (cache->val_type==RV_NONE)
+ goto undef;
+ else goto error_cache;
}else{
memset(&pval, 0, sizeof(pval));
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,
pv_value_destroy(&pval);
goto rv_str;
}else{
+ /* no PV_VAL_STR and no PV_VAL_INT => undef
+ (PV_VAL_NULL) */
pv_value_destroy(&pval);
- goto error;
+ goto undef;
}
}else{
- goto error;
+ goto eval_error;
}
}
break;
@@ -751,10 +766,19 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
goto error;
}
return 0;
+undef:
+eval_error: /* same as undefined */
+ /* handle undefined => result 0, return success */
+ *i=0;
+ return 0;
+error_cache:
+ BUG("invalid cached value:cache type %d, value type %d\n",
+ cache?cache->cache_type:0, cache?cache->val_type:0);
rv_str:
/* rv is of string type => error */
/* ERR("string in int expression\n"); */
error:
+ *i=0;
return -1;
}
@@ -762,6 +786,9 @@ error:
/** get the string value of an rv in a tmp variable
* *s=(str)rv
+ * if rv == undefined select, avp or pvar, return "".
+ * if an error occurs while evaluating a select, avp or pvar, behave as
+ * for the undefined case (and return success).
* The result points either to a temporary string or inside
* new_cache. new_cache must be non zero, initialized previously,
* and it _must_ be rval_cache_clean(...)'ed when done.
@@ -771,9 +798,9 @@ error:
* @param h - script context handle
* @param msg - sip msg
* @param tmpv - str return value (pointer to a str struct that will be
- * be filled.
+ * be filled with the conversion result)
* @param rv - rvalue to be converted
- * @param cache - cached rv value (read-only)
+ * @param cache - cached rv value (read-only), can be 0
* @param tmp_cache - used for temporary storage (so that tmpv will not
* point to possible freed data), it must be non-null,
* initialized and cleaned afterwards.
@@ -814,10 +841,9 @@ int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg,
i=run_select(tmpv, &rv->v.sel, msg);
if (unlikely(i!=0)){
if (i<0){
- goto error;
- }else { /* i>0 */
- tmpv->s="";
- tmpv->len=0;
+ goto eval_error;
+ }else { /* i>0 => undefined */
+ goto undef;
}
}
break;
@@ -828,7 +854,9 @@ int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg,
}else if (cache->val_type==RV_INT){
i=cache->c.avp_val.n;
tmpv->s=int2str(i, &tmpv->len);
- }else goto error;
+ }else if (cache->val_type==RV_NONE){
+ goto undef;
+ }else goto error_cache;
}else{
r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
&tmp_cache->c.avp_val,
@@ -842,9 +870,7 @@ int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg,
i=tmp_cache->c.avp_val.n;
tmpv->s=int2str(i, &tmpv->len);
}
- }else{
- goto error;
- }
+ }else goto undef;
}
break;
case RV_PVAR:
@@ -854,7 +880,9 @@ int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg,
}else if (cache->val_type==RV_INT){
i=cache->c.pval.ri;
tmpv->s=int2str(i, &tmpv->len);
- }else goto error;
+ }else if (cache->val_type==RV_NONE){
+ goto undef;
+ }else goto error_cache;
}else{
memset(&tmp_cache->c.pval, 0, sizeof(tmp_cache->c.pval));
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,
pv_value_destroy(&tmp_cache->c.pval);
tmpv->s=int2str(i, &tmpv->len);
}else{
+ /* no PV_VAL_STR and no PV_VAL_INT => undef
+ (PV_VAL_NULL) */
pv_value_destroy(&tmp_cache->c.pval);
- goto error;
+ goto undef;
}
}else{
- goto error;
+ goto eval_error;
}
}
break;
@@ -884,7 +914,18 @@ int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg,
goto error;
}
return 0;
+undef:
+eval_error: /* same as undefined */
+ /* handle undefined => result "", return success */
+ tmpv->s="";
+ tmpv->len=0;
+ return 0;
+error_cache:
+ BUG("invalid cached value:cache type %d, value type %d\n",
+ cache?cache->cache_type:0, cache?cache->val_type:0);
error:
+ tmpv->s="";
+ tmpv->len=0;
return -1;
}