Mercurial > libavcodec.hg
annotate eval.c @ 11816:7c2369ec6faa libavcodec
ARM: check struct offsets only when they are used
The offsets differ depending on configuration, so only check them when
they will actually be used. Presently, this is when NEON is enabled.
author | mru |
---|---|
date | Wed, 02 Jun 2010 22:05:25 +0000 |
parents | 0448680fa221 |
children |
rev | line source |
---|---|
612 | 1 /* |
4101 | 2 * 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
|
3 * Copyright (c) 2006 Oded Shimon <ods15@ods15.dyndns.org> |
612 | 4 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
5 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
6 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
612 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * 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
|
10 * version 2.1 of the License, or (at your option) any later version. |
612 | 11 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
612 | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * 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
|
18 * 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
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
612 | 20 */ |
21 | |
1106 | 22 /** |
11644
7dd2a45249a9
Remove explicit filename from Doxygen @file commands.
diego
parents:
11616
diff
changeset
|
23 * @file |
1106 | 24 * simple arithmetic expression evaluator. |
25 * | |
612 | 26 * see http://joe.hotchkiss.com/programming/eval/eval.html |
27 */ | |
28 | |
11613 | 29 #include "libavutil/avutil.h" |
10039 | 30 #include "eval.h" |
31 | |
11803 | 32 typedef struct Parser { |
11749
c6368258b694
Change eval API to take parent log context and log level offset.
michael
parents:
11739
diff
changeset
|
33 const AVClass *class; |
612 | 34 int stack_index; |
35 char *s; | |
11802
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
36 const double *const_values; |
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
37 const char * const *const_names; // NULL terminated |
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
38 double (* const *funcs1)(void *, double a); // NULL terminated |
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
39 const char * const *func1_names; // NULL terminated |
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
40 double (* const *funcs2)(void *, double a, double b); // NULL terminated |
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
41 const char * const *func2_names; // NULL terminated |
612 | 42 void *opaque; |
11749
c6368258b694
Change eval API to take parent log context and log level offset.
michael
parents:
11739
diff
changeset
|
43 int log_offset; |
c6368258b694
Change eval API to take parent log context and log level offset.
michael
parents:
11739
diff
changeset
|
44 void *log_ctx; |
4089 | 45 #define VARS 10 |
46 double var[VARS]; | |
612 | 47 } Parser; |
48 | |
11749
c6368258b694
Change eval API to take parent log context and log level offset.
michael
parents:
11739
diff
changeset
|
49 static const AVClass class = { "Eval", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT, offsetof(Parser,log_offset), offsetof(Parser,log_ctx) }; |
c6368258b694
Change eval API to take parent log context and log level offset.
michael
parents:
11739
diff
changeset
|
50 |
11803 | 51 static const int8_t si_prefixes['z' - 'E' + 1] = { |
3778 | 52 ['y'-'E']= -24, |
53 ['z'-'E']= -21, | |
54 ['a'-'E']= -18, | |
55 ['f'-'E']= -15, | |
56 ['p'-'E']= -12, | |
57 ['n'-'E']= - 9, | |
58 ['u'-'E']= - 6, | |
59 ['m'-'E']= - 3, | |
60 ['c'-'E']= - 2, | |
61 ['d'-'E']= - 1, | |
62 ['h'-'E']= 2, | |
63 ['k'-'E']= 3, | |
64 ['K'-'E']= 3, | |
65 ['M'-'E']= 6, | |
66 ['G'-'E']= 9, | |
67 ['T'-'E']= 12, | |
68 ['P'-'E']= 15, | |
69 ['E'-'E']= 18, | |
70 ['Z'-'E']= 21, | |
71 ['Y'-'E']= 24, | |
72 }; | |
3756 | 73 |
11803 | 74 double av_strtod(const char *numstr, char **tail) |
75 { | |
3778 | 76 double d; |
77 char *next; | |
9879
d54ba41c7e48
Cosmetics: rename 'name' av_strtod() param to 'numstr'. The new name
stefano
parents:
8718
diff
changeset
|
78 d = strtod(numstr, &next); |
3778 | 79 /* 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
|
80 if (next!=numstr) { |
11803 | 81 if (*next >= 'E' && *next <= 'z') { |
3778 | 82 int e= si_prefixes[*next - 'E']; |
11803 | 83 if (e) { |
84 if (next[1] == 'i') { | |
3778 | 85 d*= pow( 2, e/0.3); |
86 next+=2; | |
11803 | 87 } else { |
3778 | 88 d*= pow(10, e); |
89 next++; | |
90 } | |
91 } | |
92 } | |
93 | |
11803 | 94 if (*next=='B') { |
3778 | 95 d*=8; |
4355 | 96 next++; |
3778 | 97 } |
98 } | |
99 /* if requested, fill in tail with the position after the last parsed | |
100 character */ | |
101 if (tail) | |
102 *tail = next; | |
103 return d; | |
104 } | |
612 | 105 |
11803 | 106 static int strmatch(const char *s, const char *prefix) |
107 { | |
612 | 108 int i; |
11803 | 109 for (i=0; prefix[i]; i++) { |
110 if (prefix[i] != s[i]) return 0; | |
612 | 111 } |
112 return 1; | |
113 } | |
114 | |
11601
29fda2500178
Avoid the use of the symbol ff_expr_s for referencing AVExpr.
stefano
parents:
11597
diff
changeset
|
115 struct AVExpr { |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
116 enum { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
117 e_value, e_const, e_func0, e_func1, e_func2, |
4089 | 118 e_squish, e_gauss, e_ld, |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
119 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
|
120 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
|
121 e_last, e_st, e_while, |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
122 } type; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
123 double value; // is sign in other types |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
124 union { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
125 int const_index; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
126 double (*func0)(double); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
127 double (*func1)(void *, double); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
128 double (*func2)(void *, double, double); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
129 } a; |
11601
29fda2500178
Avoid the use of the symbol ff_expr_s for referencing AVExpr.
stefano
parents:
11597
diff
changeset
|
130 struct AVExpr *param[2]; |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
131 }; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
132 |
11803 | 133 static double eval_expr(Parser *p, AVExpr *e) |
134 { | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
135 switch (e->type) { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
136 case e_value: return e->value; |
11802
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
137 case e_const: return e->value * p->const_values[e->a.const_index]; |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
138 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
|
139 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
|
140 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
|
141 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
|
142 case e_gauss: { double d = eval_expr(p, e->param[0]); return exp(-d*d/2)/sqrt(2*M_PI); } |
4594 | 143 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
|
144 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
|
145 double d = NAN; |
11803 | 146 while (eval_expr(p, e->param[0])) |
4090
8e35dfc4ae15
add support for while() loops again ugly syntax while(condition, statements) but very simple implementation
michael
parents:
4089
diff
changeset
|
147 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
|
148 return d; |
8e35dfc4ae15
add support for while() loops again ugly syntax while(condition, statements) but very simple implementation
michael
parents:
4089
diff
changeset
|
149 } |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
150 default: { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
151 double d = eval_expr(p, e->param[0]); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
152 double d2 = eval_expr(p, e->param[1]); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
153 switch (e->type) { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
154 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
|
155 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
|
156 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
|
157 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
|
158 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
|
159 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
|
160 case e_pow: return e->value * pow(d, d2); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
161 case e_mul: return e->value * (d * d2); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
162 case e_div: return e->value * (d / d2); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
163 case e_add: return e->value * (d + d2); |
4093 | 164 case e_last:return e->value * d2; |
4594 | 165 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
|
166 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
167 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
168 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
169 return NAN; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
170 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
171 |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
172 static int parse_expr(AVExpr **e, Parser *p); |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
173 |
11803 | 174 void ff_free_expr(AVExpr *e) |
175 { | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
176 if (!e) return; |
11597 | 177 ff_free_expr(e->param[0]); |
178 ff_free_expr(e->param[1]); | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
179 av_freep(&e); |
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 |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
182 static int parse_primary(AVExpr **e, Parser *p) |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
183 { |
11803 | 184 AVExpr *d = av_mallocz(sizeof(AVExpr)); |
612 | 185 char *next= p->s; |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
186 int ret, i; |
612 | 187 |
10168
6eded00bb689
eval: Check for return value of memory allocations.
ramiro
parents:
10067
diff
changeset
|
188 if (!d) |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
189 return AVERROR(ENOMEM); |
10168
6eded00bb689
eval: Check for return value of memory allocations.
ramiro
parents:
10067
diff
changeset
|
190 |
612 | 191 /* number */ |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
192 d->value = av_strtod(p->s, &next); |
11803 | 193 if (next != p->s) { |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
194 d->type = e_value; |
612 | 195 p->s= next; |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
196 *e = d; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
197 return 0; |
612 | 198 } |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
199 d->value = 1; |
2967 | 200 |
612 | 201 /* named constants */ |
11803 | 202 for (i=0; p->const_names && p->const_names[i]; i++) { |
203 if (strmatch(p->s, p->const_names[i])) { | |
11802
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
204 p->s+= strlen(p->const_names[i]); |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
205 d->type = e_const; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
206 d->a.const_index = i; |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
207 *e = d; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
208 return 0; |
612 | 209 } |
210 } | |
2967 | 211 |
612 | 212 p->s= strchr(p->s, '('); |
11803 | 213 if (p->s==NULL) { |
11749
c6368258b694
Change eval API to take parent log context and log level offset.
michael
parents:
11739
diff
changeset
|
214 av_log(p, AV_LOG_ERROR, "undefined constant or missing (\n"); |
3754 | 215 p->s= next; |
11597 | 216 ff_free_expr(d); |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
217 return AVERROR(EINVAL); |
612 | 218 } |
219 p->s++; // "(" | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
220 if (*next == '(') { // special case do-nothing |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
221 av_freep(&d); |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
222 if ((ret = parse_expr(&d, p)) < 0) |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
223 return ret; |
11803 | 224 if (p->s[0] != ')') { |
11749
c6368258b694
Change eval API to take parent log context and log level offset.
michael
parents:
11739
diff
changeset
|
225 av_log(p, AV_LOG_ERROR, "missing )\n"); |
11597 | 226 ff_free_expr(d); |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
227 return AVERROR(EINVAL); |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
228 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
229 p->s++; // ")" |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
230 *e = d; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
231 return 0; |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
232 } |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
233 if ((ret = parse_expr(&(d->param[0]), p)) < 0) { |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
234 ff_free_expr(d); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
235 return ret; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
236 } |
11803 | 237 if (p->s[0]== ',') { |
1815 | 238 p->s++; // "," |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
239 parse_expr(&d->param[1], p); |
612 | 240 } |
11803 | 241 if (p->s[0] != ')') { |
11749
c6368258b694
Change eval API to take parent log context and log level offset.
michael
parents:
11739
diff
changeset
|
242 av_log(p, AV_LOG_ERROR, "missing )\n"); |
11597 | 243 ff_free_expr(d); |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
244 return AVERROR(EINVAL); |
1815 | 245 } |
246 p->s++; // ")" | |
2967 | 247 |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
248 d->type = e_func0; |
11803 | 249 if (strmatch(next, "sinh" )) d->a.func0 = sinh; |
250 else if (strmatch(next, "cosh" )) d->a.func0 = cosh; | |
251 else if (strmatch(next, "tanh" )) d->a.func0 = tanh; | |
252 else if (strmatch(next, "sin" )) d->a.func0 = sin; | |
253 else if (strmatch(next, "cos" )) d->a.func0 = cos; | |
254 else if (strmatch(next, "tan" )) d->a.func0 = tan; | |
255 else if (strmatch(next, "atan" )) d->a.func0 = atan; | |
256 else if (strmatch(next, "asin" )) d->a.func0 = asin; | |
257 else if (strmatch(next, "acos" )) d->a.func0 = acos; | |
258 else if (strmatch(next, "exp" )) d->a.func0 = exp; | |
259 else if (strmatch(next, "log" )) d->a.func0 = log; | |
260 else if (strmatch(next, "abs" )) d->a.func0 = fabs; | |
261 else if (strmatch(next, "squish")) d->type = e_squish; | |
262 else if (strmatch(next, "gauss" )) d->type = e_gauss; | |
263 else if (strmatch(next, "mod" )) d->type = e_mod; | |
264 else if (strmatch(next, "max" )) d->type = e_max; | |
265 else if (strmatch(next, "min" )) d->type = e_min; | |
266 else if (strmatch(next, "eq" )) d->type = e_eq; | |
267 else if (strmatch(next, "gte" )) d->type = e_gte; | |
268 else if (strmatch(next, "gt" )) d->type = e_gt; | |
269 else if (strmatch(next, "lte" )) { AVExpr *tmp = d->param[1]; d->param[1] = d->param[0]; d->param[0] = tmp; d->type = e_gt; } | |
270 else if (strmatch(next, "lt" )) { AVExpr *tmp = d->param[1]; d->param[1] = d->param[0]; d->param[0] = tmp; d->type = e_gte; } | |
271 else if (strmatch(next, "ld" )) d->type = e_ld; | |
272 else if (strmatch(next, "st" )) d->type = e_st; | |
273 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
|
274 else { |
11803 | 275 for (i=0; p->func1_names && p->func1_names[i]; i++) { |
276 if (strmatch(next, p->func1_names[i])) { | |
11802
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
277 d->a.func1 = p->funcs1[i]; |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
278 d->type = e_func1; |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
279 *e = d; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
280 return 0; |
612 | 281 } |
282 } | |
283 | |
11803 | 284 for (i=0; p->func2_names && p->func2_names[i]; i++) { |
285 if (strmatch(next, p->func2_names[i])) { | |
11802
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
286 d->a.func2 = p->funcs2[i]; |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
287 d->type = e_func2; |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
288 *e = d; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
289 return 0; |
612 | 290 } |
291 } | |
292 | |
11749
c6368258b694
Change eval API to take parent log context and log level offset.
michael
parents:
11739
diff
changeset
|
293 av_log(p, AV_LOG_ERROR, "unknown function\n"); |
11597 | 294 ff_free_expr(d); |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
295 return AVERROR(EINVAL); |
612 | 296 } |
2433 | 297 |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
298 *e = d; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
299 return 0; |
2967 | 300 } |
2436 | 301 |
11803 | 302 static AVExpr *new_eval_expr(int type, int value, AVExpr *p0, AVExpr *p1) |
303 { | |
304 AVExpr *e = av_mallocz(sizeof(AVExpr)); | |
10168
6eded00bb689
eval: Check for return value of memory allocations.
ramiro
parents:
10067
diff
changeset
|
305 if (!e) |
6eded00bb689
eval: Check for return value of memory allocations.
ramiro
parents:
10067
diff
changeset
|
306 return NULL; |
4085 | 307 e->type =type ; |
308 e->value =value ; | |
309 e->param[0] =p0 ; | |
310 e->param[1] =p1 ; | |
311 return e; | |
312 } | |
313 | |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
314 static int parse_pow(AVExpr **e, Parser *p, int *sign) |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
315 { |
4032 | 316 *sign= (*p->s == '+') - (*p->s == '-'); |
317 p->s += *sign&1; | |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
318 return parse_primary(e, p); |
2434 | 319 } |
612 | 320 |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
321 static int parse_factor(AVExpr **e, Parser *p) |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
322 { |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
323 int sign, sign2, ret; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
324 AVExpr *e0, *e1, *e2; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
325 if ((ret = parse_pow(&e0, p, &sign)) < 0) |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
326 return ret; |
2434 | 327 while(p->s[0]=='^'){ |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
328 e1 = e0; |
612 | 329 p->s++; |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
330 if ((ret = parse_pow(&e2, p, &sign2)) < 0) { |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
331 ff_free_expr(e1); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
332 return ret; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
333 } |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
334 e0 = new_eval_expr(e_pow, 1, e1, e2); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
335 if (!e0) { |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
336 ff_free_expr(e1); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
337 ff_free_expr(e2); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
338 return AVERROR(ENOMEM); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
339 } |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
340 if (e0->param[1]) e0->param[1]->value *= (sign2|1); |
612 | 341 } |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
342 if (e0) e0->value *= (sign|1); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
343 |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
344 *e = e0; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
345 return 0; |
612 | 346 } |
347 | |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
348 static int parse_term(AVExpr **e, Parser *p) |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
349 { |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
350 int ret; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
351 AVExpr *e0, *e1, *e2; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
352 if ((ret = parse_factor(&e0, p)) < 0) |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
353 return ret; |
11803 | 354 while (p->s[0]=='*' || p->s[0]=='/') { |
4085 | 355 int c= *p->s++; |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
356 e1 = e0; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
357 if ((ret = parse_factor(&e2, p)) < 0) { |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
358 ff_free_expr(e1); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
359 return ret; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
360 } |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
361 e0 = new_eval_expr(c == '*' ? e_mul : e_div, 1, e1, e2); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
362 if (!e0) { |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
363 ff_free_expr(e1); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
364 ff_free_expr(e2); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
365 return AVERROR(ENOMEM); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
366 } |
612 | 367 } |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
368 *e = e0; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
369 return 0; |
612 | 370 } |
371 | |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
372 static int parse_subexpr(AVExpr **e, Parser *p) |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
373 { |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
374 int ret; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
375 AVExpr *e0, *e1, *e2; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
376 if ((ret = parse_term(&e0, p)) < 0) |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
377 return ret; |
11803 | 378 while (*p->s == '+' || *p->s == '-') { |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
379 e1 = e0; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
380 if ((ret = parse_term(&e2, p)) < 0) { |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
381 ff_free_expr(e1); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
382 return ret; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
383 } |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
384 e0 = new_eval_expr(e_add, 1, e1, e2); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
385 if (!e0) { |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
386 ff_free_expr(e1); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
387 ff_free_expr(e2); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
388 return AVERROR(ENOMEM); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
389 } |
4089 | 390 }; |
391 | |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
392 *e = e0; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
393 return 0; |
4089 | 394 } |
395 | |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
396 static int parse_expr(AVExpr **e, Parser *p) |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
397 { |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
398 int ret; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
399 AVExpr *e0, *e1, *e2; |
11803 | 400 if (p->stack_index <= 0) //protect against stack overflows |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
401 return AVERROR(EINVAL); |
2434 | 402 p->stack_index--; |
403 | |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
404 if ((ret = parse_subexpr(&e0, p)) < 0) |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
405 return ret; |
11803 | 406 while (*p->s == ';') { |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
407 e1 = e0; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
408 if ((ret = parse_subexpr(&e2, p)) < 0) { |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
409 ff_free_expr(e1); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
410 return ret; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
411 } |
4089 | 412 p->s++; |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
413 e0 = new_eval_expr(e_last, 1, e1, e2); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
414 if (!e0) { |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
415 ff_free_expr(e1); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
416 ff_free_expr(e2); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
417 return AVERROR(ENOMEM); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
418 } |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
419 }; |
612 | 420 |
2434 | 421 p->stack_index++; |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
422 *e = e0; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
423 return 0; |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
424 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
425 |
11803 | 426 static int verify_expr(AVExpr *e) |
427 { | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
428 if (!e) return 0; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
429 switch (e->type) { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
430 case e_value: |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
431 case e_const: return 1; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
432 case e_func0: |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
433 case e_func1: |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
434 case e_squish: |
4089 | 435 case e_ld: |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
436 case e_gauss: return verify_expr(e->param[0]); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
437 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
|
438 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
439 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
440 |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
441 int ff_parse_expr(AVExpr **expr, const char *s, |
11802
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
442 const char * const *const_names, |
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
443 const char * const *func1_names, double (* const *funcs1)(void *, double), |
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
444 const char * const *func2_names, double (* const *funcs2)(void *, double, double), |
11804
3dc6ee95d63a
Cosmetics: reindent and break some overly long line.
stefano
parents:
11803
diff
changeset
|
445 int log_offset, void *log_ctx) |
11749
c6368258b694
Change eval API to take parent log context and log level offset.
michael
parents:
11739
diff
changeset
|
446 { |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
447 Parser p; |
11596
e22a96273dc4
Rename AVEvalExpr to AVExpr, as suggested by Michael.
stefano
parents:
10168
diff
changeset
|
448 AVExpr *e = NULL; |
10067
685af2860d80
eval: replace variable-length array with av_malloc/free
mru
parents:
10040
diff
changeset
|
449 char *w = av_malloc(strlen(s) + 1); |
685af2860d80
eval: replace variable-length array with av_malloc/free
mru
parents:
10040
diff
changeset
|
450 char *wp = w; |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
451 int ret = 0; |
10067
685af2860d80
eval: replace variable-length array with av_malloc/free
mru
parents:
10040
diff
changeset
|
452 |
685af2860d80
eval: replace variable-length array with av_malloc/free
mru
parents:
10040
diff
changeset
|
453 if (!w) |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
454 return AVERROR(ENOMEM); |
4095 | 455 |
456 while (*s) | |
457 if (!isspace(*s++)) *wp++ = s[-1]; | |
458 *wp++ = 0; | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
459 |
11749
c6368258b694
Change eval API to take parent log context and log level offset.
michael
parents:
11739
diff
changeset
|
460 p.class = &class; |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
461 p.stack_index=100; |
4095 | 462 p.s= w; |
11802
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
463 p.const_names = const_names; |
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
464 p.funcs1 = funcs1; |
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
465 p.func1_names = func1_names; |
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
466 p.funcs2 = funcs2; |
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
467 p.func2_names = func2_names; |
11749
c6368258b694
Change eval API to take parent log context and log level offset.
michael
parents:
11739
diff
changeset
|
468 p.log_offset = log_offset; |
c6368258b694
Change eval API to take parent log context and log level offset.
michael
parents:
11739
diff
changeset
|
469 p.log_ctx = log_ctx; |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
470 |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
471 if ((ret = parse_expr(&e, &p)) < 0) |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
472 goto end; |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
473 if (!verify_expr(e)) { |
11597 | 474 ff_free_expr(e); |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
475 ret = AVERROR(EINVAL); |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
476 goto end; |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
477 } |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
478 *expr = e; |
10067
685af2860d80
eval: replace variable-length array with av_malloc/free
mru
parents:
10040
diff
changeset
|
479 end: |
685af2860d80
eval: replace variable-length array with av_malloc/free
mru
parents:
10040
diff
changeset
|
480 av_free(w); |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
481 return ret; |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
482 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
483 |
11803 | 484 double ff_eval_expr(AVExpr *e, const double *const_values, void *opaque) |
485 { | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
486 Parser p; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
487 |
11802
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
488 p.const_values = const_values; |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
489 p.opaque = opaque; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
490 return eval_expr(&p, e); |
612 | 491 } |
492 | |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
493 int ff_parse_and_eval_expr(double *d, const char *s, |
11802
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
494 const char * const *const_names, const double *const_values, |
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
495 const char * const *func1_names, double (* const *funcs1)(void *, double), |
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
496 const char * const *func2_names, double (* const *funcs2)(void *, double, double), |
11804
3dc6ee95d63a
Cosmetics: reindent and break some overly long line.
stefano
parents:
11803
diff
changeset
|
497 void *opaque, int log_offset, void *log_ctx) |
11749
c6368258b694
Change eval API to take parent log context and log level offset.
michael
parents:
11739
diff
changeset
|
498 { |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
499 AVExpr *e = NULL; |
11802
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
500 int ret = ff_parse_expr(&e, s, const_names, func1_names, funcs1, func2_names, funcs2, log_offset, log_ctx); |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
501 |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
502 if (ret < 0) { |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
503 *d = NAN; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
504 return ret; |
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
505 } |
11802
5880d90f2b99
Cosmetics: rename ff_parse_expr() and ff_parse_and_eval_expr() parameters:
stefano
parents:
11801
diff
changeset
|
506 *d = ff_eval_expr(e, const_values, opaque); |
11597 | 507 ff_free_expr(e); |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
508 return isnan(*d) ? AVERROR(EINVAL) : 0; |
612 | 509 } |
2433 | 510 |
511 #ifdef TEST | |
2967 | 512 #undef printf |
11803 | 513 static double const_values[] = { |
2433 | 514 M_PI, |
515 M_E, | |
516 0 | |
517 }; | |
11804
3dc6ee95d63a
Cosmetics: reindent and break some overly long line.
stefano
parents:
11803
diff
changeset
|
518 |
11803 | 519 static const char *const_names[] = { |
2433 | 520 "PI", |
521 "E", | |
522 0 | |
523 }; | |
11804
3dc6ee95d63a
Cosmetics: reindent and break some overly long line.
stefano
parents:
11803
diff
changeset
|
524 |
11803 | 525 int main(void) |
526 { | |
2436 | 527 int i; |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
528 double d; |
11804
3dc6ee95d63a
Cosmetics: reindent and break some overly long line.
stefano
parents:
11803
diff
changeset
|
529 ff_parse_and_eval_expr(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", |
3dc6ee95d63a
Cosmetics: reindent and break some overly long line.
stefano
parents:
11803
diff
changeset
|
530 const_names, const_values, |
3dc6ee95d63a
Cosmetics: reindent and break some overly long line.
stefano
parents:
11803
diff
changeset
|
531 NULL, NULL, NULL, NULL, NULL, 0, NULL); |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
532 printf("%f == 12.7\n", d); |
11804
3dc6ee95d63a
Cosmetics: reindent and break some overly long line.
stefano
parents:
11803
diff
changeset
|
533 ff_parse_and_eval_expr(&d, "80G/80Gi", |
3dc6ee95d63a
Cosmetics: reindent and break some overly long line.
stefano
parents:
11803
diff
changeset
|
534 const_names, const_values, |
11805 | 535 NULL, NULL, NULL, NULL, NULL, 0, NULL); |
11801
026edf66e3a9
Make ff_parse_expr() and ff_parse_and_eval_expr() return an int
stefano
parents:
11749
diff
changeset
|
536 printf("%f == 0.931322575\n", d); |
2967 | 537 |
11803 | 538 for (i=0; i<1050; i++) { |
2436 | 539 START_TIMER |
11804
3dc6ee95d63a
Cosmetics: reindent and break some overly long line.
stefano
parents:
11803
diff
changeset
|
540 ff_parse_and_eval_expr(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", |
3dc6ee95d63a
Cosmetics: reindent and break some overly long line.
stefano
parents:
11803
diff
changeset
|
541 const_names, const_values, |
3dc6ee95d63a
Cosmetics: reindent and break some overly long line.
stefano
parents:
11803
diff
changeset
|
542 NULL, NULL, NULL, NULL, NULL, 0, NULL); |
11605 | 543 STOP_TIMER("ff_parse_and_eval_expr") |
2436 | 544 } |
6167 | 545 return 0; |
2433 | 546 } |
547 #endif |