comparison eval.c @ 11801:026edf66e3a9 libavcodec

Make ff_parse_expr() and ff_parse_and_eval_expr() return an int containing an error code. Allow these functions to convey the reason of the failure to the calling function, failure which is not always due to a parsing error but it may depend for example on a memory problem. Also fix several potential memleaks.
author stefano
date Tue, 01 Jun 2010 08:07:07 +0000
parents c6368258b694
children 5880d90f2b99
comparison
equal deleted inserted replaced
11800:966aa6b53dcf 11801:026edf66e3a9
165 } 165 }
166 } 166 }
167 return NAN; 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 void ff_free_expr(AVExpr * e) { 172 void ff_free_expr(AVExpr * e) {
173 if (!e) return; 173 if (!e) return;
174 ff_free_expr(e->param[0]); 174 ff_free_expr(e->param[0]);
175 ff_free_expr(e->param[1]); 175 ff_free_expr(e->param[1]);
176 av_freep(&e); 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 AVExpr * d = av_mallocz(sizeof(AVExpr)); 181 AVExpr * d = av_mallocz(sizeof(AVExpr));
181 char *next= p->s; 182 char *next= p->s;
182 int i; 183 int ret, i;
183 184
184 if (!d) 185 if (!d)
185 return NULL; 186 return AVERROR(ENOMEM);
186 187
187 /* number */ 188 /* number */
188 d->value = av_strtod(p->s, &next); 189 d->value = av_strtod(p->s, &next);
189 if(next != p->s){ 190 if(next != p->s){
190 d->type = e_value; 191 d->type = e_value;
191 p->s= next; 192 p->s= next;
192 return d; 193 *e = d;
194 return 0;
193 } 195 }
194 d->value = 1; 196 d->value = 1;
195 197
196 /* named constants */ 198 /* named constants */
197 for(i=0; p->const_name && p->const_name[i]; i++){ 199 for(i=0; p->const_name && p->const_name[i]; i++){
198 if(strmatch(p->s, p->const_name[i])){ 200 if(strmatch(p->s, p->const_name[i])){
199 p->s+= strlen(p->const_name[i]); 201 p->s+= strlen(p->const_name[i]);
200 d->type = e_const; 202 d->type = e_const;
201 d->a.const_index = i; 203 d->a.const_index = i;
202 return d; 204 *e = d;
205 return 0;
203 } 206 }
204 } 207 }
205 208
206 p->s= strchr(p->s, '('); 209 p->s= strchr(p->s, '(');
207 if(p->s==NULL){ 210 if(p->s==NULL){
208 av_log(p, AV_LOG_ERROR, "undefined constant or missing (\n"); 211 av_log(p, AV_LOG_ERROR, "undefined constant or missing (\n");
209 p->s= next; 212 p->s= next;
210 ff_free_expr(d); 213 ff_free_expr(d);
211 return NULL; 214 return AVERROR(EINVAL);
212 } 215 }
213 p->s++; // "(" 216 p->s++; // "("
214 if (*next == '(') { // special case do-nothing 217 if (*next == '(') { // special case do-nothing
215 av_freep(&d); 218 av_freep(&d);
216 d = parse_expr(p); 219 if ((ret = parse_expr(&d, p)) < 0)
220 return ret;
217 if(p->s[0] != ')'){ 221 if(p->s[0] != ')'){
218 av_log(p, AV_LOG_ERROR, "missing )\n"); 222 av_log(p, AV_LOG_ERROR, "missing )\n");
219 ff_free_expr(d); 223 ff_free_expr(d);
220 return NULL; 224 return AVERROR(EINVAL);
221 } 225 }
222 p->s++; // ")" 226 p->s++; // ")"
223 return d; 227 *e = d;
224 } 228 return 0;
225 d->param[0] = parse_expr(p); 229 }
230 if ((ret = parse_expr(&(d->param[0]), p)) < 0) {
231 ff_free_expr(d);
232 return ret;
233 }
226 if(p->s[0]== ','){ 234 if(p->s[0]== ','){
227 p->s++; // "," 235 p->s++; // ","
228 d->param[1] = parse_expr(p); 236 parse_expr(&d->param[1], p);
229 } 237 }
230 if(p->s[0] != ')'){ 238 if(p->s[0] != ')'){
231 av_log(p, AV_LOG_ERROR, "missing )\n"); 239 av_log(p, AV_LOG_ERROR, "missing )\n");
232 ff_free_expr(d); 240 ff_free_expr(d);
233 return NULL; 241 return AVERROR(EINVAL);
234 } 242 }
235 p->s++; // ")" 243 p->s++; // ")"
236 244
237 d->type = e_func0; 245 d->type = e_func0;
238 if( strmatch(next, "sinh" ) ) d->a.func0 = sinh; 246 if( strmatch(next, "sinh" ) ) d->a.func0 = sinh;
263 else { 271 else {
264 for(i=0; p->func1_name && p->func1_name[i]; i++){ 272 for(i=0; p->func1_name && p->func1_name[i]; i++){
265 if(strmatch(next, p->func1_name[i])){ 273 if(strmatch(next, p->func1_name[i])){
266 d->a.func1 = p->func1[i]; 274 d->a.func1 = p->func1[i];
267 d->type = e_func1; 275 d->type = e_func1;
268 return d; 276 *e = d;
277 return 0;
269 } 278 }
270 } 279 }
271 280
272 for(i=0; p->func2_name && p->func2_name[i]; i++){ 281 for(i=0; p->func2_name && p->func2_name[i]; i++){
273 if(strmatch(next, p->func2_name[i])){ 282 if(strmatch(next, p->func2_name[i])){
274 d->a.func2 = p->func2[i]; 283 d->a.func2 = p->func2[i];
275 d->type = e_func2; 284 d->type = e_func2;
276 return d; 285 *e = d;
286 return 0;
277 } 287 }
278 } 288 }
279 289
280 av_log(p, AV_LOG_ERROR, "unknown function\n"); 290 av_log(p, AV_LOG_ERROR, "unknown function\n");
281 ff_free_expr(d); 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 static AVExpr * new_eval_expr(int type, int value, AVExpr *p0, AVExpr *p1){ 299 static AVExpr * new_eval_expr(int type, int value, AVExpr *p0, AVExpr *p1){
289 AVExpr * e = av_mallocz(sizeof(AVExpr)); 300 AVExpr * e = av_mallocz(sizeof(AVExpr));
290 if (!e) 301 if (!e)
294 e->param[0] =p0 ; 305 e->param[0] =p0 ;
295 e->param[1] =p1 ; 306 e->param[1] =p1 ;
296 return e; 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 *sign= (*p->s == '+') - (*p->s == '-'); 312 *sign= (*p->s == '+') - (*p->s == '-');
301 p->s += *sign&1; 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){ 317 static int parse_factor(AVExpr **e, Parser *p)
306 int sign, sign2; 318 {
307 AVExpr * e = parse_pow(p, &sign); 319 int sign, sign2, ret;
320 AVExpr *e0, *e1, *e2;
321 if ((ret = parse_pow(&e0, p, &sign)) < 0)
322 return ret;
308 while(p->s[0]=='^'){ 323 while(p->s[0]=='^'){
324 e1 = e0;
309 p->s++; 325 p->s++;
310 e= new_eval_expr(e_pow, 1, e, parse_pow(p, &sign2)); 326 if ((ret = parse_pow(&e2, p, &sign2)) < 0) {
311 if (!e) 327 ff_free_expr(e1);
312 return NULL; 328 return ret;
313 if (e->param[1]) e->param[1]->value *= (sign2|1); 329 }
314 } 330 e0 = new_eval_expr(e_pow, 1, e1, e2);
315 if (e) e->value *= (sign|1); 331 if (!e0) {
316 return e; 332 ff_free_expr(e1);
317 } 333 ff_free_expr(e2);
318 334 return AVERROR(ENOMEM);
319 static AVExpr * parse_term(Parser *p){ 335 }
320 AVExpr * e = parse_factor(p); 336 if (e0->param[1]) e0->param[1]->value *= (sign2|1);
337 }
338 if (e0) e0->value *= (sign|1);
339
340 *e = e0;
341 return 0;
342 }
343
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 while(p->s[0]=='*' || p->s[0]=='/'){ 350 while(p->s[0]=='*' || p->s[0]=='/'){
322 int c= *p->s++; 351 int c= *p->s++;
323 e= new_eval_expr(c == '*' ? e_mul : e_div, 1, e, parse_factor(p)); 352 e1 = e0;
324 if (!e) 353 if ((ret = parse_factor(&e2, p)) < 0) {
325 return NULL; 354 ff_free_expr(e1);
326 } 355 return ret;
327 return e; 356 }
328 } 357 e0 = new_eval_expr(c == '*' ? e_mul : e_div, 1, e1, e2);
329 358 if (!e0) {
330 static AVExpr * parse_subexpr(Parser *p) { 359 ff_free_expr(e1);
331 AVExpr * e = parse_term(p); 360 ff_free_expr(e2);
361 return AVERROR(ENOMEM);
362 }
363 }
364 *e = e0;
365 return 0;
366 }
367
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 while(*p->s == '+' || *p->s == '-') { 374 while(*p->s == '+' || *p->s == '-') {
333 e= new_eval_expr(e_add, 1, e, parse_term(p)); 375 e1 = e0;
334 if (!e) 376 if ((ret = parse_term(&e2, p)) < 0) {
335 return NULL; 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;
339 } 389 return 0;
340 390 }
341 static AVExpr * parse_expr(Parser *p) { 391
342 AVExpr * e; 392 static int parse_expr(AVExpr **e, Parser *p)
343 393 {
394 int ret;
395 AVExpr *e0, *e1, *e2;
344 if(p->stack_index <= 0) //protect against stack overflows 396 if(p->stack_index <= 0) //protect against stack overflows
345 return NULL; 397 return AVERROR(EINVAL);
346 p->stack_index--; 398 p->stack_index--;
347 399
348 e = parse_subexpr(p); 400 if ((ret = parse_subexpr(&e0, p)) < 0)
349 401 return ret;
350 while(*p->s == ';') { 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 p->s++; 408 p->s++;
352 e= new_eval_expr(e_last, 1, e, parse_subexpr(p)); 409 e0 = new_eval_expr(e_last, 1, e1, e2);
353 if (!e) 410 if (!e0) {
354 return NULL; 411 ff_free_expr(e1);
412 ff_free_expr(e2);
413 return AVERROR(ENOMEM);
414 }
355 }; 415 };
356 416
357 p->stack_index++; 417 p->stack_index++;
358 418 *e = e0;
359 return e; 419 return 0;
360 } 420 }
361 421
362 static int verify_expr(AVExpr * e) { 422 static int verify_expr(AVExpr * e) {
363 if (!e) return 0; 423 if (!e) return 0;
364 switch (e->type) { 424 switch (e->type) {
371 case e_gauss: return verify_expr(e->param[0]); 431 case e_gauss: return verify_expr(e->param[0]);
372 default: return verify_expr(e->param[0]) && verify_expr(e->param[1]); 432 default: return verify_expr(e->param[0]) && verify_expr(e->param[1]);
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 const char * const *const_name, 437 const char * const *const_name,
378 const char * const *func1_name, double (* const *func1)(void *, double), 438 const char * const *func1_name, double (* const *func1)(void *, double),
379 const char * const *func2_name, double (* const *func2)(void *, double, double), 439 const char * const *func2_name, double (* const *func2)(void *, double, double),
380 int log_offset, void *log_ctx) 440 int log_offset, void *log_ctx)
381 { 441 {
382 Parser p; 442 Parser p;
383 AVExpr *e = NULL; 443 AVExpr *e = NULL;
384 char *w = av_malloc(strlen(s) + 1); 444 char *w = av_malloc(strlen(s) + 1);
385 char *wp = w; 445 char *wp = w;
446 int ret = 0;
386 447
387 if (!w) 448 if (!w)
388 goto end; 449 return AVERROR(ENOMEM);
389 450
390 while (*s) 451 while (*s)
391 if (!isspace(*s++)) *wp++ = s[-1]; 452 if (!isspace(*s++)) *wp++ = s[-1];
392 *wp++ = 0; 453 *wp++ = 0;
393 454
400 p.func2 = func2; 461 p.func2 = func2;
401 p.func2_name = func2_name; 462 p.func2_name = func2_name;
402 p.log_offset = log_offset; 463 p.log_offset = log_offset;
403 p.log_ctx = log_ctx; 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 if (!verify_expr(e)) { 468 if (!verify_expr(e)) {
407 ff_free_expr(e); 469 ff_free_expr(e);
408 e = NULL; 470 ret = AVERROR(EINVAL);
409 } 471 goto end;
472 }
473 *expr = e;
410 end: 474 end:
411 av_free(w); 475 av_free(w);
412 return e; 476 return ret;
413 } 477 }
414 478
415 double ff_eval_expr(AVExpr * e, const double *const_value, void *opaque) { 479 double ff_eval_expr(AVExpr * e, const double *const_value, void *opaque) {
416 Parser p; 480 Parser p;
417 481
418 p.const_value= const_value; 482 p.const_value= const_value;
419 p.opaque = opaque; 483 p.opaque = opaque;
420 return eval_expr(&p, e); 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 const char * const *const_name, const double *const_value, 488 const char * const *const_name, const double *const_value,
425 const char * const *func1_name, double (* const *func1)(void *, double), 489 const char * const *func1_name, double (* const *func1)(void *, double),
426 const char * const *func2_name, double (* const *func2)(void *, double, double), 490 const char * const *func2_name, double (* const *func2)(void *, double, double),
427 void *opaque, int log_offset, void *log_ctx) 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); 493 AVExpr *e = NULL;
430 double d; 494 int ret = ff_parse_expr(&e, s, const_name, func1_name, func1, func2_name, func2, log_offset, log_ctx);
431 if (!e) return NAN; 495
432 d = ff_eval_expr(e, const_value, opaque); 496 if (ret < 0) {
497 *d = NAN;
498 return ret;
499 }
500 *d = ff_eval_expr(e, const_value, opaque);
433 ff_free_expr(e); 501 ff_free_expr(e);
434 return d; 502 return isnan(*d) ? AVERROR(EINVAL) : 0;
435 } 503 }
436 504
437 #ifdef TEST 505 #ifdef TEST
438 #undef printf 506 #undef printf
439 static double const_values[]={ 507 static double const_values[]={
446 "E", 514 "E",
447 0 515 0
448 }; 516 };
449 int main(void){ 517 int main(void){
450 int i; 518 int i;
451 printf("%f == 12.7\n", ff_parse_and_eval_expr("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL)); 519 double d;
452 printf("%f == 0.931322575\n", ff_parse_and_eval_expr("80G/80Gi", const_names, const_values, NULL, NULL, NULL, NULL, NULL, NULL)); 520 ff_parse_and_eval_expr(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL);
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 for(i=0; i<1050; i++){ 525 for(i=0; i<1050; i++){
455 START_TIMER 526 START_TIMER
456 ff_parse_and_eval_expr("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL); 527 ff_parse_and_eval_expr(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, NULL);
457 STOP_TIMER("ff_parse_and_eval_expr") 528 STOP_TIMER("ff_parse_and_eval_expr")
458 } 529 }
459 return 0; 530 return 0;
460 } 531 }
461 #endif 532 #endif