Mercurial > libavcodec.hg
annotate eval.c @ 9896:bbefbca72722 libavcodec
Drop code that attempts to decode frames that are prefixed by junk.
Too often it ends up decoding random data into noise without detecting
it (for example after seeking of some MP3 data with oddly often occurring
startcode emulation).
Fixes issue1154.
| author | michael |
|---|---|
| date | Tue, 30 Jun 2009 03:57:27 +0000 |
| parents | e934c5f8f4a9 |
| children | e557e75172b0 |
| rev | line source |
|---|---|
| 612 | 1 /* |
| 2 * simple arithmetic expression evaluator | |
| 3 * | |
| 4101 | 4 * Copyright (c) 2002-2006 Michael Niedermayer <michaelni@gmx.at> |
|
4099
5e5c34470242
I hope noone minds, adding myself to eval.c copyright...
ods15
parents:
4095
diff
changeset
|
5 * Copyright (c) 2006 Oded Shimon <ods15@ods15.dyndns.org> |
| 612 | 6 * |
|
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
7 * This file is part of FFmpeg. |
|
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
8 * |
|
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
9 * FFmpeg is free software; you can redistribute it and/or |
| 612 | 10 * modify it under the terms of the GNU Lesser General Public |
| 11 * License as published by the Free Software Foundation; either | |
|
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
12 * version 2.1 of the License, or (at your option) any later version. |
| 612 | 13 * |
|
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
14 * FFmpeg is distributed in the hope that it will be useful, |
| 612 | 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 17 * Lesser General Public License for more details. | |
| 18 * | |
| 19 * You should have received a copy of the GNU Lesser General Public | |
|
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
20 * License along with FFmpeg; if not, write to the Free Software |
|
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
2967
diff
changeset
|
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 612 | 22 */ |
| 23 | |
| 1106 | 24 /** |
|
8718
e9d9d946f213
Use full internal pathname in doxygen @file directives.
diego
parents:
8320
diff
changeset
|
25 * @file libavcodec/eval.c |
| 1106 | 26 * simple arithmetic expression evaluator. |
| 27 * | |
| 612 | 28 * see http://joe.hotchkiss.com/programming/eval/eval.html |
| 29 */ | |
| 30 | |
| 1057 | 31 #include "avcodec.h" |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
32 #include "eval.h" |
| 1057 | 33 |
| 612 | 34 #include <stdio.h> |
| 35 #include <stdlib.h> | |
| 36 #include <string.h> | |
| 37 #include <math.h> | |
| 38 | |
|
614
b786f15df503
NAN doesnt exist on FreeBSD patch by (R?mi Guyomarch <rguyom at pobox dot com>)
michaelni
parents:
612
diff
changeset
|
39 #ifndef NAN |
| 3753 | 40 #define NAN 0.0/0.0 |
|
614
b786f15df503
NAN doesnt exist on FreeBSD patch by (R?mi Guyomarch <rguyom at pobox dot com>)
michaelni
parents:
612
diff
changeset
|
41 #endif |
|
b786f15df503
NAN doesnt exist on FreeBSD patch by (R?mi Guyomarch <rguyom at pobox dot com>)
michaelni
parents:
612
diff
changeset
|
42 |
| 627 | 43 #ifndef M_PI |
| 44 #define M_PI 3.14159265358979323846 | |
| 45 #endif | |
| 46 | |
| 612 | 47 typedef struct Parser{ |
| 48 int stack_index; | |
| 49 char *s; | |
| 8320 | 50 const double *const_value; |
| 51 const char * const *const_name; // NULL terminated | |
| 612 | 52 double (**func1)(void *, double a); // NULL terminated |
| 1057 | 53 const char **func1_name; // NULL terminated |
| 612 | 54 double (**func2)(void *, double a, double b); // NULL terminated |
| 8320 | 55 const char **func2_name; // NULL terminated |
| 612 | 56 void *opaque; |
| 6324 | 57 const char **error; |
| 4089 | 58 #define VARS 10 |
| 59 double var[VARS]; | |
| 612 | 60 } Parser; |
| 61 | |
| 7129 | 62 static const int8_t si_prefixes['z' - 'E' + 1]={ |
| 3778 | 63 ['y'-'E']= -24, |
| 64 ['z'-'E']= -21, | |
| 65 ['a'-'E']= -18, | |
| 66 ['f'-'E']= -15, | |
| 67 ['p'-'E']= -12, | |
| 68 ['n'-'E']= - 9, | |
| 69 ['u'-'E']= - 6, | |
| 70 ['m'-'E']= - 3, | |
| 71 ['c'-'E']= - 2, | |
| 72 ['d'-'E']= - 1, | |
| 73 ['h'-'E']= 2, | |
| 74 ['k'-'E']= 3, | |
| 75 ['K'-'E']= 3, | |
| 76 ['M'-'E']= 6, | |
| 77 ['G'-'E']= 9, | |
| 78 ['T'-'E']= 12, | |
| 79 ['P'-'E']= 15, | |
| 80 ['E'-'E']= 18, | |
| 81 ['Z'-'E']= 21, | |
| 82 ['Y'-'E']= 24, | |
| 83 }; | |
| 3756 | 84 |
| 9880 | 85 double av_strtod(const char *numstr, char **tail) { |
| 3778 | 86 double d; |
| 87 char *next; | |
|
9879
d54ba41c7e48
Cosmetics: rename 'name' av_strtod() param to 'numstr'. The new name
stefano
parents:
8718
diff
changeset
|
88 d = strtod(numstr, &next); |
| 3778 | 89 /* if parsing succeeded, check for and interpret postfixes */ |
|
9879
d54ba41c7e48
Cosmetics: rename 'name' av_strtod() param to 'numstr'. The new name
stefano
parents:
8718
diff
changeset
|
90 if (next!=numstr) { |
| 3778 | 91 |
| 92 if(*next >= 'E' && *next <= 'z'){ | |
| 93 int e= si_prefixes[*next - 'E']; | |
| 94 if(e){ | |
| 95 if(next[1] == 'i'){ | |
| 96 d*= pow( 2, e/0.3); | |
| 97 next+=2; | |
| 98 }else{ | |
| 99 d*= pow(10, e); | |
| 100 next++; | |
| 101 } | |
| 102 } | |
| 103 } | |
| 104 | |
| 105 if(*next=='B') { | |
| 106 d*=8; | |
| 4355 | 107 next++; |
| 3778 | 108 } |
| 109 } | |
| 110 /* if requested, fill in tail with the position after the last parsed | |
| 111 character */ | |
| 112 if (tail) | |
| 113 *tail = next; | |
| 114 return d; | |
| 115 } | |
| 612 | 116 |
| 1057 | 117 static int strmatch(const char *s, const char *prefix){ |
| 612 | 118 int i; |
| 119 for(i=0; prefix[i]; i++){ | |
| 120 if(prefix[i] != s[i]) return 0; | |
| 121 } | |
| 122 return 1; | |
| 123 } | |
| 124 | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
125 struct ff_expr_s { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
126 enum { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
127 e_value, e_const, e_func0, e_func1, e_func2, |
| 4089 | 128 e_squish, e_gauss, e_ld, |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
129 e_mod, e_max, e_min, e_eq, e_gt, e_gte, |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
130 e_pow, e_mul, e_div, e_add, |
|
4090
8e35dfc4ae15
add support for while() loops again ugly syntax while(condition, statements) but very simple implementation
michael
parents:
4089
diff
changeset
|
131 e_last, e_st, e_while, |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
132 } type; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
133 double value; // is sign in other types |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
134 union { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
135 int const_index; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
136 double (*func0)(double); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
137 double (*func1)(void *, double); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
138 double (*func2)(void *, double, double); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
139 } a; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
140 AVEvalExpr * param[2]; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
141 }; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
142 |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
143 static double eval_expr(Parser * p, AVEvalExpr * e) { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
144 switch (e->type) { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
145 case e_value: return e->value; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
146 case e_const: return e->value * p->const_value[e->a.const_index]; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
147 case e_func0: return e->value * e->a.func0(eval_expr(p, e->param[0])); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
148 case e_func1: return e->value * e->a.func1(p->opaque, eval_expr(p, e->param[0])); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
149 case e_func2: return e->value * e->a.func2(p->opaque, eval_expr(p, e->param[0]), eval_expr(p, e->param[1])); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
150 case e_squish: return 1/(1+exp(4*eval_expr(p, e->param[0]))); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
151 case e_gauss: { double d = eval_expr(p, e->param[0]); return exp(-d*d/2)/sqrt(2*M_PI); } |
| 4594 | 152 case e_ld: return e->value * p->var[av_clip(eval_expr(p, e->param[0]), 0, VARS-1)]; |
|
4090
8e35dfc4ae15
add support for while() loops again ugly syntax while(condition, statements) but very simple implementation
michael
parents:
4089
diff
changeset
|
153 case e_while: { |
|
4092
772ab2a1deaa
shut gcc warning, also makes sense for NAN to be returned if the loop was never executed
ods15
parents:
4090
diff
changeset
|
154 double d = NAN; |
|
4090
8e35dfc4ae15
add support for while() loops again ugly syntax while(condition, statements) but very simple implementation
michael
parents:
4089
diff
changeset
|
155 while(eval_expr(p, e->param[0])) |
|
8e35dfc4ae15
add support for while() loops again ugly syntax while(condition, statements) but very simple implementation
michael
parents:
4089
diff
changeset
|
156 d=eval_expr(p, e->param[1]); |
|
8e35dfc4ae15
add support for while() loops again ugly syntax while(condition, statements) but very simple implementation
michael
parents:
4089
diff
changeset
|
157 return d; |
|
8e35dfc4ae15
add support for while() loops again ugly syntax while(condition, statements) but very simple implementation
michael
parents:
4089
diff
changeset
|
158 } |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
159 default: { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
160 double d = eval_expr(p, e->param[0]); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
161 double d2 = eval_expr(p, e->param[1]); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
162 switch (e->type) { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
163 case e_mod: return e->value * (d - floor(d/d2)*d2); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
164 case e_max: return e->value * (d > d2 ? d : d2); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
165 case e_min: return e->value * (d < d2 ? d : d2); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
166 case e_eq: return e->value * (d == d2 ? 1.0 : 0.0); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
167 case e_gt: return e->value * (d > d2 ? 1.0 : 0.0); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
168 case e_gte: return e->value * (d >= d2 ? 1.0 : 0.0); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
169 case e_pow: return e->value * pow(d, d2); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
170 case e_mul: return e->value * (d * d2); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
171 case e_div: return e->value * (d / d2); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
172 case e_add: return e->value * (d + d2); |
| 4093 | 173 case e_last:return e->value * d2; |
| 4594 | 174 case e_st : return e->value * (p->var[av_clip(d, 0, VARS-1)]= d2); |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
175 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
176 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
177 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
178 return NAN; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
179 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
180 |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
181 static AVEvalExpr * parse_expr(Parser *p); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
182 |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
183 void ff_eval_free(AVEvalExpr * e) { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
184 if (!e) return; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
185 ff_eval_free(e->param[0]); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
186 ff_eval_free(e->param[1]); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
187 av_freep(&e); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
188 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
189 |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
190 static AVEvalExpr * parse_primary(Parser *p) { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
191 AVEvalExpr * d = av_mallocz(sizeof(AVEvalExpr)); |
| 612 | 192 char *next= p->s; |
| 193 int i; | |
| 194 | |
| 195 /* number */ | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
196 d->value = av_strtod(p->s, &next); |
| 612 | 197 if(next != p->s){ |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
198 d->type = e_value; |
| 612 | 199 p->s= next; |
| 2434 | 200 return d; |
| 612 | 201 } |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
202 d->value = 1; |
| 2967 | 203 |
| 612 | 204 /* named constants */ |
| 2433 | 205 for(i=0; p->const_name && p->const_name[i]; i++){ |
| 612 | 206 if(strmatch(p->s, p->const_name[i])){ |
| 207 p->s+= strlen(p->const_name[i]); | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
208 d->type = e_const; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
209 d->a.const_index = i; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
210 return d; |
| 612 | 211 } |
| 212 } | |
| 2967 | 213 |
| 612 | 214 p->s= strchr(p->s, '('); |
| 215 if(p->s==NULL){ | |
| 6840 | 216 *p->error = "undefined constant or missing ("; |
| 3754 | 217 p->s= next; |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
218 ff_eval_free(d); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
219 return NULL; |
| 612 | 220 } |
| 221 p->s++; // "(" | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
222 if (*next == '(') { // special case do-nothing |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
223 av_freep(&d); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
224 d = parse_expr(p); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
225 if(p->s[0] != ')'){ |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
226 *p->error = "missing )"; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
227 ff_eval_free(d); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
228 return NULL; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
229 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
230 p->s++; // ")" |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
231 return d; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
232 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
233 d->param[0] = parse_expr(p); |
| 1815 | 234 if(p->s[0]== ','){ |
| 235 p->s++; // "," | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
236 d->param[1] = parse_expr(p); |
| 612 | 237 } |
| 1815 | 238 if(p->s[0] != ')'){ |
|
3770
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
239 *p->error = "missing )"; |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
240 ff_eval_free(d); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
241 return NULL; |
| 1815 | 242 } |
| 243 p->s++; // ")" | |
| 2967 | 244 |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
245 d->type = e_func0; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
246 if( strmatch(next, "sinh" ) ) d->a.func0 = sinh; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
247 else if( strmatch(next, "cosh" ) ) d->a.func0 = cosh; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
248 else if( strmatch(next, "tanh" ) ) d->a.func0 = tanh; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
249 else if( strmatch(next, "sin" ) ) d->a.func0 = sin; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
250 else if( strmatch(next, "cos" ) ) d->a.func0 = cos; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
251 else if( strmatch(next, "tan" ) ) d->a.func0 = tan; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
252 else if( strmatch(next, "atan" ) ) d->a.func0 = atan; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
253 else if( strmatch(next, "asin" ) ) d->a.func0 = asin; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
254 else if( strmatch(next, "acos" ) ) d->a.func0 = acos; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
255 else if( strmatch(next, "exp" ) ) d->a.func0 = exp; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
256 else if( strmatch(next, "log" ) ) d->a.func0 = log; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
257 else if( strmatch(next, "abs" ) ) d->a.func0 = fabs; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
258 else if( strmatch(next, "squish") ) d->type = e_squish; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
259 else if( strmatch(next, "gauss" ) ) d->type = e_gauss; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
260 else if( strmatch(next, "mod" ) ) d->type = e_mod; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
261 else if( strmatch(next, "max" ) ) d->type = e_max; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
262 else if( strmatch(next, "min" ) ) d->type = e_min; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
263 else if( strmatch(next, "eq" ) ) d->type = e_eq; |
|
4087
d4cdb9f6e888
possible bug of 'gte' being read as 'gt', same with 'lte'
ods15
parents:
4086
diff
changeset
|
264 else if( strmatch(next, "gte" ) ) d->type = e_gte; |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
265 else if( strmatch(next, "gt" ) ) d->type = e_gt; |
|
4087
d4cdb9f6e888
possible bug of 'gte' being read as 'gt', same with 'lte'
ods15
parents:
4086
diff
changeset
|
266 else if( strmatch(next, "lte" ) ) { AVEvalExpr * tmp = d->param[1]; d->param[1] = d->param[0]; d->param[0] = tmp; d->type = e_gt; } |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
267 else if( strmatch(next, "lt" ) ) { AVEvalExpr * tmp = d->param[1]; d->param[1] = d->param[0]; d->param[0] = tmp; d->type = e_gte; } |
| 4089 | 268 else if( strmatch(next, "ld" ) ) d->type = e_ld; |
| 269 else if( strmatch(next, "st" ) ) d->type = e_st; | |
|
4090
8e35dfc4ae15
add support for while() loops again ugly syntax while(condition, statements) but very simple implementation
michael
parents:
4089
diff
changeset
|
270 else if( strmatch(next, "while" ) ) d->type = e_while; |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
271 else { |
| 612 | 272 for(i=0; p->func1_name && p->func1_name[i]; i++){ |
| 273 if(strmatch(next, p->func1_name[i])){ | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
274 d->a.func1 = p->func1[i]; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
275 d->type = e_func1; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
276 return d; |
| 612 | 277 } |
| 278 } | |
| 279 | |
| 280 for(i=0; p->func2_name && p->func2_name[i]; i++){ | |
| 281 if(strmatch(next, p->func2_name[i])){ | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
282 d->a.func2 = p->func2[i]; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
283 d->type = e_func2; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
284 return d; |
| 612 | 285 } |
| 286 } | |
| 287 | |
|
3770
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
288 *p->error = "unknown function"; |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
289 ff_eval_free(d); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
290 return NULL; |
| 612 | 291 } |
| 2433 | 292 |
| 2434 | 293 return d; |
| 2967 | 294 } |
| 2436 | 295 |
| 4085 | 296 static AVEvalExpr * new_eval_expr(int type, int value, AVEvalExpr *p0, AVEvalExpr *p1){ |
| 297 AVEvalExpr * e = av_mallocz(sizeof(AVEvalExpr)); | |
| 298 e->type =type ; | |
| 299 e->value =value ; | |
| 300 e->param[0] =p0 ; | |
| 301 e->param[1] =p1 ; | |
| 302 return e; | |
| 303 } | |
| 304 | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
305 static AVEvalExpr * parse_pow(Parser *p, int *sign){ |
| 4032 | 306 *sign= (*p->s == '+') - (*p->s == '-'); |
| 307 p->s += *sign&1; | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
308 return parse_primary(p); |
| 2434 | 309 } |
| 612 | 310 |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
311 static AVEvalExpr * parse_factor(Parser *p){ |
| 4032 | 312 int sign, sign2; |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
313 AVEvalExpr * e = parse_pow(p, &sign); |
| 2434 | 314 while(p->s[0]=='^'){ |
| 612 | 315 p->s++; |
| 4086 | 316 e= new_eval_expr(e_pow, 1, e, parse_pow(p, &sign2)); |
| 317 if (e->param[1]) e->param[1]->value *= (sign2|1); | |
| 612 | 318 } |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
319 if (e) e->value *= (sign|1); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
320 return e; |
| 612 | 321 } |
| 322 | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
323 static AVEvalExpr * parse_term(Parser *p){ |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
324 AVEvalExpr * e = parse_factor(p); |
| 2434 | 325 while(p->s[0]=='*' || p->s[0]=='/'){ |
| 4085 | 326 int c= *p->s++; |
| 327 e= new_eval_expr(c == '*' ? e_mul : e_div, 1, e, parse_factor(p)); | |
| 612 | 328 } |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
329 return e; |
| 612 | 330 } |
| 331 | |
| 4089 | 332 static AVEvalExpr * parse_subexpr(Parser *p) { |
| 333 AVEvalExpr * e = parse_term(p); | |
| 334 while(*p->s == '+' || *p->s == '-') { | |
| 335 e= new_eval_expr(e_add, 1, e, parse_term(p)); | |
| 336 }; | |
| 337 | |
| 338 return e; | |
| 339 } | |
| 340 | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
341 static AVEvalExpr * parse_expr(Parser *p) { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
342 AVEvalExpr * e; |
| 612 | 343 |
| 2434 | 344 if(p->stack_index <= 0) //protect against stack overflows |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
345 return NULL; |
| 2434 | 346 p->stack_index--; |
| 347 | |
| 4089 | 348 e = parse_subexpr(p); |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
349 |
| 4089 | 350 while(*p->s == ';') { |
| 351 p->s++; | |
| 352 e= new_eval_expr(e_last, 1, e, parse_subexpr(p)); | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
353 }; |
| 612 | 354 |
| 2434 | 355 p->stack_index++; |
| 612 | 356 |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
357 return e; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
358 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
359 |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
360 static int verify_expr(AVEvalExpr * e) { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
361 if (!e) return 0; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
362 switch (e->type) { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
363 case e_value: |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
364 case e_const: return 1; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
365 case e_func0: |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
366 case e_func1: |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
367 case e_squish: |
| 4089 | 368 case e_ld: |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
369 case e_gauss: return verify_expr(e->param[0]); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
370 default: return verify_expr(e->param[0]) && verify_expr(e->param[1]); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
371 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
372 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
373 |
| 8320 | 374 AVEvalExpr * ff_parse(const char *s, const char * const *const_name, |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
375 double (**func1)(void *, double), const char **func1_name, |
| 8320 | 376 double (**func2)(void *, double, double), const char **func2_name, |
| 6324 | 377 const char **error){ |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
378 Parser p; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
379 AVEvalExpr * e; |
| 4095 | 380 char w[strlen(s) + 1], * wp = w; |
| 381 | |
| 382 while (*s) | |
| 383 if (!isspace(*s++)) *wp++ = s[-1]; | |
| 384 *wp++ = 0; | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
385 |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
386 p.stack_index=100; |
| 4095 | 387 p.s= w; |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
388 p.const_name = const_name; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
389 p.func1 = func1; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
390 p.func1_name = func1_name; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
391 p.func2 = func2; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
392 p.func2_name = func2_name; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
393 p.error= error; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
394 |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
395 e = parse_expr(&p); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
396 if (!verify_expr(e)) { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
397 ff_eval_free(e); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
398 return NULL; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
399 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
400 return e; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
401 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
402 |
| 8320 | 403 double ff_parse_eval(AVEvalExpr * e, const double *const_value, void *opaque) { |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
404 Parser p; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
405 |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
406 p.const_value= const_value; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
407 p.opaque = opaque; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
408 return eval_expr(&p, e); |
| 612 | 409 } |
| 410 | |
| 8320 | 411 double ff_eval2(const char *s, const double *const_value, const char * const *const_name, |
| 1057 | 412 double (**func1)(void *, double), const char **func1_name, |
| 8320 | 413 double (**func2)(void *, double, double), const char **func2_name, |
| 6324 | 414 void *opaque, const char **error){ |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
415 AVEvalExpr * e = ff_parse(s, const_name, func1, func1_name, func2, func2_name, error); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
416 double d; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
417 if (!e) return NAN; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
418 d = ff_parse_eval(e, const_value, opaque); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
419 ff_eval_free(e); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
420 return d; |
| 612 | 421 } |
| 2433 | 422 |
| 423 #ifdef TEST | |
| 2967 | 424 #undef printf |
| 2433 | 425 static double const_values[]={ |
| 426 M_PI, | |
| 427 M_E, | |
| 428 0 | |
| 429 }; | |
| 430 static const char *const_names[]={ | |
| 431 "PI", | |
| 432 "E", | |
| 433 0 | |
| 434 }; | |
| 6167 | 435 int main(void){ |
| 2436 | 436 int i; |
|
8108
5de6db4225d6
Fix test program build: ff_eval was replaced by ff_eval2.
diego
parents:
7824
diff
changeset
|
437 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)); |
|
5de6db4225d6
Fix test program build: ff_eval was replaced by ff_eval2.
diego
parents:
7824
diff
changeset
|
438 printf("%f == 0.931322575\n", ff_eval2("80G/80Gi", const_values, const_names, NULL, NULL, NULL, NULL, NULL, NULL)); |
| 2967 | 439 |
| 2436 | 440 for(i=0; i<1050; i++){ |
| 441 START_TIMER | |
|
8108
5de6db4225d6
Fix test program build: ff_eval was replaced by ff_eval2.
diego
parents:
7824
diff
changeset
|
442 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); |
|
5de6db4225d6
Fix test program build: ff_eval was replaced by ff_eval2.
diego
parents:
7824
diff
changeset
|
443 STOP_TIMER("ff_eval2") |
| 2436 | 444 } |
| 6167 | 445 return 0; |
| 2433 | 446 } |
| 447 #endif |
