[FFmpeg-devel] [PATCH 2/2] Make ff_parse_expr() and ff_parse_and_eval_expr() return an int containing an error code.
Stefano Sabatini
stefano.sabatini-lala
Thu May 20 02:08:46 CEST 2010
Allow these functions to convey to the calling application the reason
of the failure, which is not always due to a parsing error but for
example it may depend on a memory problem.
---
libavcodec/eval.c | 44 ++++++++++++++++++++++++++------------------
libavcodec/eval.h | 17 ++++++++++++-----
libavcodec/opt.c | 6 +++---
libavcodec/ratecontrol.c | 8 ++++----
4 files changed, 45 insertions(+), 30 deletions(-)
diff --git a/libavcodec/eval.c b/libavcodec/eval.c
index c1bb42d..727acbf 100644
--- a/libavcodec/eval.c
+++ b/libavcodec/eval.c
@@ -373,19 +373,20 @@ static int verify_expr(AVExpr * e) {
}
}
-AVExpr *ff_parse_expr(const char *s,
+int ff_parse_expr(AVExpr **expr, const char *s,
const char * const *const_name,
const char * const *func1_name, double (* const *func1)(void *, double),
const char * const *func2_name, double (* const *func2)(void *, double, double),
int log_offset, void *log_ctx)
{
Parser p;
- AVExpr *e = NULL;
char *w = av_malloc(strlen(s) + 1);
char *wp = w;
+ int res = 0;
+ *expr = NULL;
if (!w)
- goto end;
+ return AVERROR(ENOMEM);
while (*s)
if (!isspace(*s++)) *wp++ = s[-1];
@@ -402,14 +403,14 @@ AVExpr *ff_parse_expr(const char *s,
p.log_offset = log_offset;
p.log_ctx = log_ctx;
- e = parse_expr(&p);
- if (!verify_expr(e)) {
- ff_free_expr(e);
- e = NULL;
+ *expr = parse_expr(&p);
+ if (!verify_expr(*expr)) {
+ ff_free_expr(*expr);
+ *expr = NULL;
+ res = AVERROR(EINVAL);
}
-end:
av_free(w);
- return e;
+ return res;
}
double ff_eval_expr(AVExpr * e, const double *const_value, void *opaque) {
@@ -420,18 +421,22 @@ double ff_eval_expr(AVExpr * e, const double *const_value, void *opaque) {
return eval_expr(&p, e);
}
-double ff_parse_and_eval_expr(const char *s,
+int ff_parse_and_eval_expr(double *d, const char *s,
const char * const *const_name, const double *const_value,
const char * const *func1_name, double (* const *func1)(void *, double),
const char * const *func2_name, double (* const *func2)(void *, double, double),
void *opaque, int log_offset, void *log_ctx)
{
- AVExpr *e = ff_parse_expr(s, const_name, func1_name, func1, func2_name, func2, log_offset, log_ctx);
- double d;
- if (!e) return NAN;
- d = ff_eval_expr(e, const_value, opaque);
+ AVExpr *e = NULL;
+ int res = ff_parse_expr(&e, s, const_name, func1_name, func1, func2_name, func2, log_offset, log_ctx);
+
+ if (res < 0) {
+ *d = NAN;
+ return res;
+ }
+ *d = ff_eval_expr(e, const_value, opaque);
ff_free_expr(e);
- return d;
+ return isnan(*d) ? AVERROR(EINVAL) : 0;
}
#ifdef TEST
@@ -448,12 +453,15 @@ static const char *const_names[]={
};
int main(void){
int i;
- printf("%f == 12.7\n", ff_parse_and_eval_expr("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL));
- printf("%f == 0.931322575\n", ff_parse_and_eval_expr("80G/80Gi", const_names, const_values, NULL, NULL, NULL, NULL, NULL, NULL));
+ double d;
+ ff_parse_and_eval_expr(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL);
+ printf("%f == 12.7\n", d);
+ ff_parse_and_eval_expr(&d, "80G/80Gi", const_names, const_values, NULL, NULL, NULL, NULL, NULL, NULL);
+ printf("%f == 0.931322575\n", d);
for(i=0; i<1050; i++){
START_TIMER
- ff_parse_and_eval_expr("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL);
+ ff_parse_and_eval_expr(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL);
STOP_TIMER("ff_parse_and_eval_expr")
}
return 0;
diff --git a/libavcodec/eval.h b/libavcodec/eval.h
index d0004b1..0efacbb 100644
--- a/libavcodec/eval.h
+++ b/libavcodec/eval.h
@@ -32,6 +32,8 @@ typedef struct AVExpr AVExpr;
* Parses and evaluates an expression.
* Note, this is significantly slower than ff_eval_expr().
*
+ * @param res a pointer to a double where is put the result value of
+ * the expression, or NAN in case of invalid expression
* @param s expression as a zero terminated string for example "1+2^3+5*5+sin(2/3)"
* @param const_name NULL terminated array of zero terminated strings of constant identifers for example {"PI", "E", 0}
* @param const_value a zero terminated array of values for the identifers from const_name
@@ -41,9 +43,10 @@ typedef struct AVExpr AVExpr;
* @param func2 NULL terminated array of function pointers for functions which take 2 arguments
* @param opaque a pointer which will be passed to all functions from func1 and func2
* @param log_ctx parent logging context
- * @return the value of the expression
+ * @return 0 in case of success, a negative value corresponding to an
+ * AVERROR code otherwise
*/
-double ff_parse_and_eval_expr(const char *s,
+int ff_parse_and_eval_expr(double *res, const char *s,
const char * const *const_name, const double *const_value,
const char * const *func1_name, double (* const *func1)(void *, double),
const char * const *func2_name, double (* const *func2)(void *, double, double),
@@ -52,6 +55,10 @@ double ff_parse_and_eval_expr(const char *s,
/**
* Parses an expression.
*
+ * @param expr a pointer where is put an AVExpr containing the parsed
+ * value in case of successfull parsing, or NULL otherwise.
+ * The pointed to AVExpr must be freed with ff_free_expr() by the user
+ * when it is not needed anymore.
* @param s expression as a zero terminated string for example "1+2^3+5*5+sin(2/3)"
* @param const_name NULL terminated array of zero terminated strings of constant identifers for example {"PI", "E", 0}
* @param func1_name NULL terminated array of zero terminated strings of func1 identifers
@@ -59,10 +66,10 @@ double ff_parse_and_eval_expr(const char *s,
* @param func2_name NULL terminated array of zero terminated strings of func2 identifers
* @param func2 NULL terminated array of function pointers for functions which take 2 arguments
* @param log_ctx parent logging context
- * @return AVExpr which must be freed with ff_free_expr() by the user when it is not needed anymore
- * NULL if anything went wrong
+ * @return 0 in case of success, a negative value corresponding to an
+ * AVERROR code otherwise
*/
-AVExpr *ff_parse_expr(const char *s,
+int ff_parse_expr(AVExpr **expr, const char *s,
const char * const *const_name,
const char * const *func1_name, double (* const *func1)(void *, double),
const char * const *func2_name, double (* const *func2)(void *, double, double),
diff --git a/libavcodec/opt.c b/libavcodec/opt.c
index 24696e1..8473d90 100644
--- a/libavcodec/opt.c
+++ b/libavcodec/opt.c
@@ -165,10 +165,10 @@ int av_set_string3(void *obj, const char *name, const char *val, int alloc, cons
else if(!strcmp(buf, "none" )) d= 0;
else if(!strcmp(buf, "all" )) d= ~0;
else {
- d = ff_parse_and_eval_expr(buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
- if (isnan(d)){
+ int res = ff_parse_and_eval_expr(&d, buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
+ if (res < 0) {
av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val);
- return AVERROR(EINVAL);
+ return res;
}
}
}
diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c
index fe6e4b0..375815a 100644
--- a/libavcodec/ratecontrol.c
+++ b/libavcodec/ratecontrol.c
@@ -66,7 +66,7 @@ static inline double bits2qp(RateControlEntry *rce, double bits){
int ff_rate_control_init(MpegEncContext *s)
{
RateControlContext *rcc= &s->rc_context;
- int i;
+ int i, res;
static const char * const const_names[]={
"PI",
"E",
@@ -106,10 +106,10 @@ int ff_rate_control_init(MpegEncContext *s)
};
emms_c();
- rcc->rc_eq_eval = ff_parse_expr(s->avctx->rc_eq ? s->avctx->rc_eq : "tex^qComp", const_names, func1_names, func1, NULL, NULL, 0, s->avctx);
- if (!rcc->rc_eq_eval) {
+ res = ff_parse_expr(&rcc->rc_eq_eval, s->avctx->rc_eq ? s->avctx->rc_eq : "tex^qComp", const_names, func1_names, func1, NULL, NULL, 0, s->avctx);
+ if (res < 0) {
av_log(s->avctx, AV_LOG_ERROR, "Error parsing rc_eq \"%s\"\n", s->avctx->rc_eq);
- return -1;
+ return res;
}
for(i=0; i<5; i++){
--
1.7.1
More information about the ffmpeg-devel
mailing list