X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Feval.c;h=134c43f08b441672ef83d6656765a084ff6a22b1;hb=c1736936982e9b0d3400462eda2b0bf410f6e003;hp=e6394c39c157f0edbaccea6f2e324c7e60ddd2b2;hpb=f8a80fd69df1735730f1b3c7f37506ffe0570d0d;p=ffmpeg diff --git a/libavcodec/eval.c b/libavcodec/eval.c index e6394c39c15..134c43f08b4 100644 --- a/libavcodec/eval.c +++ b/libavcodec/eval.c @@ -22,45 +22,37 @@ */ /** - * @file eval.c + * @file libavcodec/eval.c * simple arithmetic expression evaluator. * * see http://joe.hotchkiss.com/programming/eval/eval.html */ -#include "avcodec.h" -#include "mpegvideo.h" -#include "eval.h" - #include #include #include #include -#ifndef NAN - #define NAN 0.0/0.0 -#endif - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif +#include "libavutil/mathematics.h" +#include "avcodec.h" +#include "eval.h" typedef struct Parser{ int stack_index; char *s; - double *const_value; - const char **const_name; // NULL terminated + const double *const_value; + const char * const *const_name; // NULL terminated double (**func1)(void *, double a); // NULL terminated const char **func1_name; // NULL terminated double (**func2)(void *, double a, double b); // NULL terminated - char **func2_name; // NULL terminated + const char **func2_name; // NULL terminated void *opaque; - char **error; + const char **error; #define VARS 10 double var[VARS]; } Parser; -static int8_t si_prefixes['z' - 'E' + 1]={ +static const int8_t si_prefixes['z' - 'E' + 1]={ ['y'-'E']= -24, ['z'-'E']= -21, ['a'-'E']= -18, @@ -83,16 +75,12 @@ static int8_t si_prefixes['z' - 'E' + 1]={ ['Y'-'E']= 24, }; -/** strtod() function extended with 'k', 'M', 'G', 'ki', 'Mi', 'Gi' and 'B' - * postfixes. This allows using f.e. kB, MiB, G and B as a postfix. This - * function assumes that the unit of numbers is bits not bytes. - */ -static double av_strtod(const char *name, char **tail) { +double av_strtod(const char *numstr, char **tail) { double d; char *next; - d = strtod(name, &next); + d = strtod(numstr, &next); /* if parsing succeeded, check for and interpret postfixes */ - if (next!=name) { + if (next!=numstr) { if(*next >= 'E' && *next <= 'z'){ int e= si_prefixes[*next - 'E']; @@ -197,6 +185,9 @@ static AVEvalExpr * parse_primary(Parser *p) { char *next= p->s; int i; + if (!d) + return NULL; + /* number */ d->value = av_strtod(p->s, &next); if(next != p->s){ @@ -218,7 +209,7 @@ static AVEvalExpr * parse_primary(Parser *p) { p->s= strchr(p->s, '('); if(p->s==NULL){ - *p->error = "missing ("; + *p->error = "undefined constant or missing ("; p->s= next; ff_eval_free(d); return NULL; @@ -300,6 +291,8 @@ static AVEvalExpr * parse_primary(Parser *p) { static AVEvalExpr * new_eval_expr(int type, int value, AVEvalExpr *p0, AVEvalExpr *p1){ AVEvalExpr * e = av_mallocz(sizeof(AVEvalExpr)); + if (!e) + return NULL; e->type =type ; e->value =value ; e->param[0] =p0 ; @@ -319,6 +312,8 @@ static AVEvalExpr * parse_factor(Parser *p){ while(p->s[0]=='^'){ p->s++; e= new_eval_expr(e_pow, 1, e, parse_pow(p, &sign2)); + if (!e) + return NULL; if (e->param[1]) e->param[1]->value *= (sign2|1); } if (e) e->value *= (sign|1); @@ -330,6 +325,8 @@ static AVEvalExpr * parse_term(Parser *p){ while(p->s[0]=='*' || p->s[0]=='/'){ int c= *p->s++; e= new_eval_expr(c == '*' ? e_mul : e_div, 1, e, parse_factor(p)); + if (!e) + return NULL; } return e; } @@ -338,6 +335,8 @@ static AVEvalExpr * parse_subexpr(Parser *p) { AVEvalExpr * e = parse_term(p); while(*p->s == '+' || *p->s == '-') { e= new_eval_expr(e_add, 1, e, parse_term(p)); + if (!e) + return NULL; }; return e; @@ -355,6 +354,8 @@ static AVEvalExpr * parse_expr(Parser *p) { while(*p->s == ';') { p->s++; e= new_eval_expr(e_last, 1, e, parse_subexpr(p)); + if (!e) + return NULL; }; p->stack_index++; @@ -376,13 +377,17 @@ static int verify_expr(AVEvalExpr * e) { } } -AVEvalExpr * ff_parse(char *s, const char **const_name, +AVEvalExpr * ff_parse(const char *s, const char * const *const_name, double (**func1)(void *, double), const char **func1_name, - double (**func2)(void *, double, double), char **func2_name, - char **error){ + double (**func2)(void *, double, double), const char **func2_name, + const char **error){ Parser p; - AVEvalExpr * e; - char w[strlen(s) + 1], * wp = w; + AVEvalExpr *e = NULL; + char *w = av_malloc(strlen(s) + 1); + char *wp = w; + + if (!w) + goto end; while (*s) if (!isspace(*s++)) *wp++ = s[-1]; @@ -400,12 +405,14 @@ AVEvalExpr * ff_parse(char *s, const char **const_name, e = parse_expr(&p); if (!verify_expr(e)) { ff_eval_free(e); - return NULL; + e = NULL; } +end: + av_free(w); return e; } -double ff_parse_eval(AVEvalExpr * e, double *const_value, void *opaque) { +double ff_parse_eval(AVEvalExpr * e, const double *const_value, void *opaque) { Parser p; p.const_value= const_value; @@ -413,10 +420,10 @@ double ff_parse_eval(AVEvalExpr * e, double *const_value, void *opaque) { return eval_expr(&p, e); } -double ff_eval2(char *s, double *const_value, const char **const_name, +double ff_eval2(const char *s, const double *const_value, const char * const *const_name, double (**func1)(void *, double), const char **func1_name, - double (**func2)(void *, double, double), char **func2_name, - void *opaque, char **error){ + double (**func2)(void *, double, double), const char **func2_name, + void *opaque, const char **error){ AVEvalExpr * e = ff_parse(s, const_name, func1, func1_name, func2, func2_name, error); double d; if (!e) return NAN; @@ -425,20 +432,6 @@ double ff_eval2(char *s, double *const_value, const char **const_name, return d; } -#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0) -attribute_deprecated double ff_eval(char *s, double *const_value, const char **const_name, - double (**func1)(void *, double), const char **func1_name, - double (**func2)(void *, double, double), char **func2_name, - void *opaque){ - char *error=NULL; - double ret; - ret = ff_eval2(s, const_value, const_name, func1, func1_name, func2, func2_name, opaque, &error); - if (error) - av_log(NULL, AV_LOG_ERROR, "Error evaluating \"%s\": %s\n", s, error); - return ret; -} -#endif - #ifdef TEST #undef printf static double const_values[]={ @@ -451,15 +444,16 @@ static const char *const_names[]={ "E", 0 }; -main(void){ +int main(void){ int i; - printf("%f == 12.7\n", ff_eval("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_values, const_names, NULL, NULL, NULL, NULL, NULL)); - printf("%f == 0.931322575\n", ff_eval("80G/80Gi", const_values, const_names, NULL, NULL, NULL, NULL, NULL)); + printf("%f == 12.7\n", ff_eval2("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_values, const_names, NULL, NULL, NULL, NULL, NULL, NULL)); + printf("%f == 0.931322575\n", ff_eval2("80G/80Gi", const_values, const_names, NULL, NULL, NULL, NULL, NULL, NULL)); for(i=0; i<1050; i++){ START_TIMER - ff_eval("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_values, const_names, NULL, NULL, NULL, NULL, NULL); - STOP_TIMER("ff_eval") + ff_eval2("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_values, const_names, NULL, NULL, NULL, NULL, NULL, NULL); + STOP_TIMER("ff_eval2") } + return 0; } #endif