Revision 9ace13b4 libavcodec/eval.c
libavcodec/eval.c  

167  167 
return NAN; 
168  168 
} 
169  169  
170 
static AVExpr * parse_expr(Parser *p);


170 
static int parse_expr(AVExpr **e, Parser *p);


171  171  
172  172 
void ff_free_expr(AVExpr * e) { 
173  173 
if (!e) return; 
...  ...  
176  176 
av_freep(&e); 
177  177 
} 
178  178  
179 
static AVExpr * parse_primary(Parser *p) { 

179 
static int parse_primary(AVExpr **e, Parser *p) 

180 
{ 

180  181 
AVExpr * d = av_mallocz(sizeof(AVExpr)); 
181  182 
char *next= p>s; 
182 
int i; 

183 
int ret, i;


183  184  
184  185 
if (!d) 
185 
return NULL;


186 
return AVERROR(ENOMEM);


186  187  
187  188 
/* number */ 
188  189 
d>value = av_strtod(p>s, &next); 
189  190 
if(next != p>s){ 
190  191 
d>type = e_value; 
191  192 
p>s= next; 
192 
return d; 

193 
*e = d; 

194 
return 0; 

193  195 
} 
194  196 
d>value = 1; 
195  197  
...  ...  
199  201 
p>s+= strlen(p>const_name[i]); 
200  202 
d>type = e_const; 
201  203 
d>a.const_index = i; 
202 
return d; 

204 
*e = d; 

205 
return 0; 

203  206 
} 
204  207 
} 
205  208  
...  ...  
208  211 
av_log(p, AV_LOG_ERROR, "undefined constant or missing (\n"); 
209  212 
p>s= next; 
210  213 
ff_free_expr(d); 
211 
return NULL;


214 
return AVERROR(EINVAL);


212  215 
} 
213  216 
p>s++; // "(" 
214  217 
if (*next == '(') { // special case donothing 
215  218 
av_freep(&d); 
216 
d = parse_expr(p); 

219 
if ((ret = parse_expr(&d, p)) < 0) 

220 
return ret; 

217  221 
if(p>s[0] != ')'){ 
218  222 
av_log(p, AV_LOG_ERROR, "missing )\n"); 
219  223 
ff_free_expr(d); 
220 
return NULL;


224 
return AVERROR(EINVAL);


221  225 
} 
222  226 
p>s++; // ")" 
223 
return d; 

227 
*e = d; 

228 
return 0; 

229 
} 

230 
if ((ret = parse_expr(&(d>param[0]), p)) < 0) { 

231 
ff_free_expr(d); 

232 
return ret; 

224  233 
} 
225 
d>param[0] = parse_expr(p); 

226  234 
if(p>s[0]== ','){ 
227  235 
p>s++; // "," 
228 
d>param[1] = parse_expr(p);


236 
parse_expr(&d>param[1], p);


229  237 
} 
230  238 
if(p>s[0] != ')'){ 
231  239 
av_log(p, AV_LOG_ERROR, "missing )\n"); 
232  240 
ff_free_expr(d); 
233 
return NULL;


241 
return AVERROR(EINVAL);


234  242 
} 
235  243 
p>s++; // ")" 
236  244  
...  ...  
265  273 
if(strmatch(next, p>func1_name[i])){ 
266  274 
d>a.func1 = p>func1[i]; 
267  275 
d>type = e_func1; 
268 
return d; 

276 
*e = d; 

277 
return 0; 

269  278 
} 
270  279 
} 
271  280  
...  ...  
273  282 
if(strmatch(next, p>func2_name[i])){ 
274  283 
d>a.func2 = p>func2[i]; 
275  284 
d>type = e_func2; 
276 
return d; 

285 
*e = d; 

286 
return 0; 

277  287 
} 
278  288 
} 
279  289  
280  290 
av_log(p, AV_LOG_ERROR, "unknown function\n"); 
281  291 
ff_free_expr(d); 
282 
return NULL;


292 
return AVERROR(EINVAL);


283  293 
} 
284  294  
285 
return d; 

295 
*e = d; 

296 
return 0; 

286  297 
} 
287  298  
288  299 
static AVExpr * new_eval_expr(int type, int value, AVExpr *p0, AVExpr *p1){ 
...  ...  
296  307 
return e; 
297  308 
} 
298  309  
299 
static AVExpr * parse_pow(Parser *p, int *sign){ 

310 
static int parse_pow(AVExpr **e, Parser *p, int *sign) 

311 
{ 

300  312 
*sign= (*p>s == '+')  (*p>s == ''); 
301  313 
p>s += *sign&1; 
302 
return parse_primary(p); 

314 
return parse_primary(e, p);


303  315 
} 
304  316  
305 
static AVExpr * parse_factor(Parser *p){ 

306 
int sign, sign2; 

307 
AVExpr * e = parse_pow(p, &sign); 

317 
static int parse_factor(AVExpr **e, Parser *p) 

318 
{ 

319 
int sign, sign2, ret; 

320 
AVExpr *e0, *e1, *e2; 

321 
if ((ret = parse_pow(&e0, p, &sign)) < 0) 

322 
return ret; 

308  323 
while(p>s[0]=='^'){ 
324 
e1 = e0; 

309  325 
p>s++; 
310 
e= new_eval_expr(e_pow, 1, e, parse_pow(p, &sign2)); 

311 
if (!e) 

312 
return NULL; 

313 
if (e>param[1]) e>param[1]>value *= (sign21); 

326 
if ((ret = parse_pow(&e2, p, &sign2)) < 0) { 

327 
ff_free_expr(e1); 

328 
return ret; 

329 
} 

330 
e0 = new_eval_expr(e_pow, 1, e1, e2); 

331 
if (!e0) { 

332 
ff_free_expr(e1); 

333 
ff_free_expr(e2); 

334 
return AVERROR(ENOMEM); 

335 
} 

336 
if (e0>param[1]) e0>param[1]>value *= (sign21); 

314  337 
} 
315 
if (e) e>value *= (sign1); 

316 
return e; 

338 
if (e0) e0>value *= (sign1); 

339  
340 
*e = e0; 

341 
return 0; 

317  342 
} 
318  343  
319 
static AVExpr * parse_term(Parser *p){ 

320 
AVExpr * e = parse_factor(p); 

344 
static int parse_term(AVExpr **e, Parser *p) 

345 
{ 

346 
int ret; 

347 
AVExpr *e0, *e1, *e2; 

348 
if ((ret = parse_factor(&e0, p)) < 0) 

349 
return ret; 

321  350 
while(p>s[0]=='*'  p>s[0]=='/'){ 
322  351 
int c= *p>s++; 
323 
e= new_eval_expr(c == '*' ? e_mul : e_div, 1, e, parse_factor(p)); 

324 
if (!e) 

325 
return NULL; 

352 
e1 = e0; 

353 
if ((ret = parse_factor(&e2, p)) < 0) { 

354 
ff_free_expr(e1); 

355 
return ret; 

356 
} 

357 
e0 = new_eval_expr(c == '*' ? e_mul : e_div, 1, e1, e2); 

358 
if (!e0) { 

359 
ff_free_expr(e1); 

360 
ff_free_expr(e2); 

361 
return AVERROR(ENOMEM); 

362 
} 

326  363 
} 
327 
return e; 

364 
*e = e0; 

365 
return 0; 

328  366 
} 
329  367  
330 
static AVExpr * parse_subexpr(Parser *p) { 

331 
AVExpr * e = parse_term(p); 

368 
static int parse_subexpr(AVExpr **e, Parser *p) 

369 
{ 

370 
int ret; 

371 
AVExpr *e0, *e1, *e2; 

372 
if ((ret = parse_term(&e0, p)) < 0) 

373 
return ret; 

332  374 
while(*p>s == '+'  *p>s == '') { 
333 
e= new_eval_expr(e_add, 1, e, parse_term(p)); 

334 
if (!e) 

335 
return NULL; 

375 
e1 = e0; 

376 
if ((ret = parse_term(&e2, p)) < 0) { 

377 
ff_free_expr(e1); 

378 
return ret; 

379 
} 

380 
e0 = new_eval_expr(e_add, 1, e1, e2); 

381 
if (!e0) { 

382 
ff_free_expr(e1); 

383 
ff_free_expr(e2); 

384 
return AVERROR(ENOMEM); 

385 
} 

336  386 
}; 
337  387  
338 
return e; 

388 
*e = e0; 

389 
return 0; 

339  390 
} 
340  391  
341 
static AVExpr * parse_expr(Parser *p) { 

342 
AVExpr * e; 

343  
392 
static int parse_expr(AVExpr **e, Parser *p) 

393 
{ 

394 
int ret; 

395 
AVExpr *e0, *e1, *e2; 

344  396 
if(p>stack_index <= 0) //protect against stack overflows 
345 
return NULL;


397 
return AVERROR(EINVAL);


346  398 
p>stack_index; 
347  399  
348 
e = parse_subexpr(p);


349  
400 
if ((ret = parse_subexpr(&e0, p)) < 0)


401 
return ret; 

350  402 
while(*p>s == ';') { 
403 
e1 = e0; 

404 
if ((ret = parse_subexpr(&e2, p)) < 0) { 

405 
ff_free_expr(e1); 

406 
return ret; 

407 
} 

351  408 
p>s++; 
352 
e= new_eval_expr(e_last, 1, e, parse_subexpr(p)); 

353 
if (!e) 

354 
return NULL; 

409 
e0 = new_eval_expr(e_last, 1, e1, e2); 

410 
if (!e0) { 

411 
ff_free_expr(e1); 

412 
ff_free_expr(e2); 

413 
return AVERROR(ENOMEM); 

414 
} 

355  415 
}; 
356  416  
357  417 
p>stack_index++; 
358  
359 
return e;


418 
*e = e0; 

419 
return 0;


360  420 
} 
361  421  
362  422 
static int verify_expr(AVExpr * e) { 
...  ...  
373  433 
} 
374  434 
} 
375  435  
376 
AVExpr *ff_parse_expr(const char *s,


436 
int ff_parse_expr(AVExpr **expr, const char *s,


377  437 
const char * const *const_name, 
378  438 
const char * const *func1_name, double (* const *func1)(void *, double), 
379  439 
const char * const *func2_name, double (* const *func2)(void *, double, double), 
...  ...  
383  443 
AVExpr *e = NULL; 
384  444 
char *w = av_malloc(strlen(s) + 1); 
385  445 
char *wp = w; 
446 
int ret = 0; 

386  447  
387  448 
if (!w) 
388 
goto end;


449 
return AVERROR(ENOMEM);


389  450  
390  451 
while (*s) 
391  452 
if (!isspace(*s++)) *wp++ = s[1]; 
...  ...  
402  463 
p.log_offset = log_offset; 
403  464 
p.log_ctx = log_ctx; 
404  465  
405 
e = parse_expr(&p); 

466 
if ((ret = parse_expr(&e, &p)) < 0) 

467 
goto end; 

406  468 
if (!verify_expr(e)) { 
407  469 
ff_free_expr(e); 
408 
e = NULL; 

470 
ret = AVERROR(EINVAL); 

471 
goto end; 

409  472 
} 
473 
*expr = e; 

410  474 
end: 
411  475 
av_free(w); 
412 
return e;


476 
return ret;


413  477 
} 
414  478  
415  479 
double ff_eval_expr(AVExpr * e, const double *const_value, void *opaque) { 
...  ...  
420  484 
return eval_expr(&p, e); 
421  485 
} 
422  486  
423 
double ff_parse_and_eval_expr(const char *s,


487 
int ff_parse_and_eval_expr(double *d, const char *s,


424  488 
const char * const *const_name, const double *const_value, 
425  489 
const char * const *func1_name, double (* const *func1)(void *, double), 
426  490 
const char * const *func2_name, double (* const *func2)(void *, double, double), 
427  491 
void *opaque, int log_offset, void *log_ctx) 
428  492 
{ 
429 
AVExpr *e = ff_parse_expr(s, const_name, func1_name, func1, func2_name, func2, log_offset, log_ctx); 

430 
double d; 

431 
if (!e) return NAN; 

432 
d = ff_eval_expr(e, const_value, opaque); 

493 
AVExpr *e = NULL; 

494 
int ret = ff_parse_expr(&e, s, const_name, func1_name, func1, func2_name, func2, log_offset, log_ctx); 

495  
496 
if (ret < 0) { 

497 
*d = NAN; 

498 
return ret; 

499 
} 

500 
*d = ff_eval_expr(e, const_value, opaque); 

433  501 
ff_free_expr(e); 
434 
return d;


502 
return isnan(*d) ? AVERROR(EINVAL) : 0;


435  503 
} 
436  504  
437  505 
#ifdef TEST 
...  ...  
448  516 
}; 
449  517 
int main(void){ 
450  518 
int i; 
451 
printf("%f == 12.7\n", ff_parse_and_eval_expr("1+(52)^(31)+1/2+sin(PI)max(2.2,3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL)); 

452 
printf("%f == 0.931322575\n", ff_parse_and_eval_expr("80G/80Gi", const_names, const_values, NULL, NULL, NULL, NULL, NULL, NULL)); 

519 
double d; 

520 
ff_parse_and_eval_expr(&d, "1+(52)^(31)+1/2+sin(PI)max(2.2,3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL); 

521 
printf("%f == 12.7\n", d); 

522 
ff_parse_and_eval_expr(&d, "80G/80Gi", const_names, const_values, NULL, NULL, NULL, NULL, NULL, NULL); 

523 
printf("%f == 0.931322575\n", d); 

453  524  
454  525 
for(i=0; i<1050; i++){ 
455  526 
START_TIMER 
456 
ff_parse_and_eval_expr("1+(52)^(31)+1/2+sin(PI)max(2.2,3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL); 

527 
ff_parse_and_eval_expr(&d, "1+(52)^(31)+1/2+sin(PI)max(2.2,3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL);


457  528 
STOP_TIMER("ff_parse_and_eval_expr") 
458  529 
} 
459  530 
return 0; 
Also available in: Unified diff