1/* 2 * Copyright (c) 2005-2014 Rich Felker, et al. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sublicense, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24#include <errno.h> 25#include <limits.h> 26#include <math.h> 27#include <stdarg.h> 28#include <stddef.h> 29#include <stdint.h> 30#include <stdio.h> 31#include <string.h> 32#include <float.h> 33 34#include "avstring.h" 35#include "libm.h" 36 37typedef struct FFFILE { 38 size_t buf_size; 39 unsigned char *buf; 40 unsigned char *rpos, *rend; 41 unsigned char *shend; 42 ptrdiff_t shlim, shcnt; 43 void *cookie; 44 size_t (*read)(struct FFFILE *, unsigned char *, size_t); 45} FFFILE; 46 47#define SIZE_hh -2 48#define SIZE_h -1 49#define SIZE_def 0 50#define SIZE_l 1 51#define SIZE_L 2 52#define SIZE_ll 3 53 54#define shcnt(f) ((f)->shcnt + ((f)->rpos - (f)->buf)) 55 56static int fftoread(FFFILE *f) 57{ 58 f->rpos = f->rend = f->buf + f->buf_size; 59 return 0; 60} 61 62static size_t ffstring_read(FFFILE *f, unsigned char *buf, size_t len) 63{ 64 char *src = f->cookie; 65 size_t k = len+256; 66 char *end = memchr(src, 0, k); 67 68 if (end) k = end-src; 69 if (k < len) len = k; 70 memcpy(buf, src, len); 71 f->rpos = (void *)(src+len); 72 f->rend = (void *)(src+k); 73 f->cookie = src+k; 74 75 return len; 76} 77 78static int ffuflow(FFFILE *f) 79{ 80 unsigned char c; 81 if (!fftoread(f) && f->read(f, &c, 1)==1) return c; 82 return EOF; 83} 84 85static void ffshlim(FFFILE *f, ptrdiff_t lim) 86{ 87 f->shlim = lim; 88 f->shcnt = f->buf - f->rpos; 89 /* If lim is nonzero, rend must be a valid pointer. */ 90 if (lim && f->rend - f->rpos > lim) 91 f->shend = f->rpos + lim; 92 else 93 f->shend = f->rend; 94} 95 96static int ffshgetc(FFFILE *f) 97{ 98 int c; 99 ptrdiff_t cnt = shcnt(f); 100 if (f->shlim && cnt >= f->shlim || (c=ffuflow(f)) < 0) { 101 f->shcnt = f->buf - f->rpos + cnt; 102 f->shend = 0; 103 return EOF; 104 } 105 cnt++; 106 if (f->shlim && f->rend - f->rpos > f->shlim - cnt) 107 f->shend = f->rpos + (f->shlim - cnt); 108 else 109 f->shend = f->rend; 110 f->shcnt = f->buf - f->rpos + cnt; 111 if (f->rpos[-1] != c) f->rpos[-1] = c; 112 return c; 113} 114 115#define shlim(f, lim) ffshlim((f), (lim)) 116#define shgetc(f) (((f)->rpos < (f)->shend) ? *(f)->rpos++ : ffshgetc(f)) 117#define shunget(f) ((f)->shend ? (void)(f)->rpos-- : (void)0) 118 119static const unsigned char table[] = { -1, 120 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 121 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 122 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 123 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, 124 -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 125 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1, 126 -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 127 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1, 128 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 129 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 130 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 131 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 132 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 133 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 134 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 135 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 136}; 137 138static unsigned long long ffintscan(FFFILE *f, unsigned base, int pok, unsigned long long lim) 139{ 140 const unsigned char *val = table+1; 141 int c, neg=0; 142 unsigned x; 143 unsigned long long y; 144 if (base > 36 || base == 1) { 145 errno = EINVAL; 146 return 0; 147 } 148 while (av_isspace((c=shgetc(f)))); 149 if (c=='+' || c=='-') { 150 neg = -(c=='-'); 151 c = shgetc(f); 152 } 153 if ((base == 0 || base == 16) && c=='0') { 154 c = shgetc(f); 155 if ((c|32)=='x') { 156 c = shgetc(f); 157 if (val[c]>=16) { 158 shunget(f); 159 if (pok) shunget(f); 160 else shlim(f, 0); 161 return 0; 162 } 163 base = 16; 164 } else if (base == 0) { 165 base = 8; 166 } 167 } else { 168 if (base == 0) base = 10; 169 if (val[c] >= base) { 170 shunget(f); 171 shlim(f, 0); 172 errno = EINVAL; 173 return 0; 174 } 175 } 176 if (base == 10) { 177 for (x=0; c-'0'<10U && x<=UINT_MAX/10-1; c=shgetc(f)) 178 x = x*10 + (c-'0'); 179 for (y=x; c-'0'<10U && y<=ULLONG_MAX/10 && 10*y<=ULLONG_MAX-(c-'0'); c=shgetc(f)) 180 y = y*10 + (c-'0'); 181 if (c-'0'>=10U) goto done; 182 } else if (!(base & base-1)) { 183 int bs = "\0\1\2\4\7\3\6\5"[(0x17*base)>>5&7]; 184 for (x=0; val[c]<base && x<=UINT_MAX/32; c=shgetc(f)) 185 x = x<<bs | val[c]; 186 for (y=x; val[c]<base && y<=ULLONG_MAX>>bs; c=shgetc(f)) 187 y = y<<bs | val[c]; 188 } else { 189 for (x=0; val[c]<base && x<=UINT_MAX/36-1; c=shgetc(f)) 190 x = x*base + val[c]; 191 for (y=x; val[c]<base && y<=ULLONG_MAX/base && base*y<=ULLONG_MAX-val[c]; c=shgetc(f)) 192 y = y*base + val[c]; 193 } 194 if (val[c]<base) { 195 for (; val[c]<base; c=shgetc(f)); 196 errno = ERANGE; 197 y = lim; 198 if (lim&1) neg = 0; 199 } 200done: 201 shunget(f); 202 if (y>=lim) { 203 if (!(lim&1) && !neg) { 204 errno = ERANGE; 205 return lim-1; 206 } else if (y>lim) { 207 errno = ERANGE; 208 return lim; 209 } 210 } 211 return (y^neg)-neg; 212} 213 214static long long scanexp(FFFILE *f, int pok) 215{ 216 int c; 217 int x; 218 long long y; 219 int neg = 0; 220 221 c = shgetc(f); 222 if (c=='+' || c=='-') { 223 neg = (c=='-'); 224 c = shgetc(f); 225 if (c-'0'>=10U && pok) shunget(f); 226 } 227 if (c-'0'>=10U) { 228 shunget(f); 229 return LLONG_MIN; 230 } 231 for (x=0; c-'0'<10U && x<INT_MAX/10; c = shgetc(f)) 232 x = 10*x + (c-'0'); 233 for (y=x; c-'0'<10U && y<LLONG_MAX/100; c = shgetc(f)) 234 y = 10*y + (c-'0'); 235 for (; c-'0'<10U; c = shgetc(f)); 236 shunget(f); 237 return neg ? -y : y; 238} 239 240#define LD_B1B_DIG 2 241#define LD_B1B_MAX 9007199, 254740991 242#define KMAX 128 243#define MASK (KMAX-1) 244 245static double decfloat(FFFILE *f, int c, int bits, int emin, int sign, int pok) 246{ 247 uint32_t x[KMAX]; 248 static const uint32_t th[] = { LD_B1B_MAX }; 249 int i, j, k, a, z; 250 long long lrp=0, dc=0; 251 long long e10=0; 252 int lnz = 0; 253 int gotdig = 0, gotrad = 0; 254 int rp; 255 int e2; 256 int emax = -emin-bits+3; 257 int denormal = 0; 258 double y; 259 double frac=0; 260 double bias=0; 261 static const int p10s[] = { 10, 100, 1000, 10000, 262 100000, 1000000, 10000000, 100000000 }; 263 264 j=0; 265 k=0; 266 267 /* Don't let leading zeros consume buffer space */ 268 for (; c=='0'; c = shgetc(f)) gotdig=1; 269 if (c=='.') { 270 gotrad = 1; 271 for (c = shgetc(f); c=='0'; c = shgetc(f)) gotdig=1, lrp--; 272 } 273 274 x[0] = 0; 275 for (; c-'0'<10U || c=='.'; c = shgetc(f)) { 276 if (c == '.') { 277 if (gotrad) break; 278 gotrad = 1; 279 lrp = dc; 280 } else if (k < KMAX-3) { 281 dc++; 282 if (c!='0') lnz = dc; 283 if (j) x[k] = x[k]*10 + c-'0'; 284 else x[k] = c-'0'; 285 if (++j==9) { 286 k++; 287 j=0; 288 } 289 gotdig=1; 290 } else { 291 dc++; 292 if (c!='0') { 293 lnz = (KMAX-4)*9; 294 x[KMAX-4] |= 1; 295 } 296 } 297 } 298 if (!gotrad) lrp=dc; 299 300 if (gotdig && (c|32)=='e') { 301 e10 = scanexp(f, pok); 302 if (e10 == LLONG_MIN) { 303 if (pok) { 304 shunget(f); 305 } else { 306 shlim(f, 0); 307 return 0; 308 } 309 e10 = 0; 310 } 311 lrp += e10; 312 } else if (c>=0) { 313 shunget(f); 314 } 315 if (!gotdig) { 316 errno = EINVAL; 317 shlim(f, 0); 318 return 0; 319 } 320 321 /* Handle zero specially to avoid nasty special cases later */ 322 if (!x[0]) return sign * 0.0; 323 324 /* Optimize small integers (w/no exponent) and over/under-flow */ 325 if (lrp==dc && dc<10 && (bits>30 || x[0]>>bits==0)) 326 return sign * (double)x[0]; 327 if (lrp > -emin/2) { 328 errno = ERANGE; 329 return sign * DBL_MAX * DBL_MAX; 330 } 331 if (lrp < emin-2*DBL_MANT_DIG) { 332 errno = ERANGE; 333 return sign * DBL_MIN * DBL_MIN; 334 } 335 336 /* Align incomplete final B1B digit */ 337 if (j) { 338 for (; j<9; j++) x[k]*=10; 339 k++; 340 j=0; 341 } 342 343 a = 0; 344 z = k; 345 e2 = 0; 346 rp = lrp; 347 348 /* Optimize small to mid-size integers (even in exp. notation) */ 349 if (lnz<9 && lnz<=rp && rp < 18) { 350 int bitlim; 351 if (rp == 9) return sign * (double)x[0]; 352 if (rp < 9) return sign * (double)x[0] / p10s[8-rp]; 353 bitlim = bits-3*(int)(rp-9); 354 if (bitlim>30 || x[0]>>bitlim==0) 355 return sign * (double)x[0] * p10s[rp-10]; 356 } 357 358 /* Drop trailing zeros */ 359 for (; !x[z-1]; z--); 360 361 /* Align radix point to B1B digit boundary */ 362 if (rp % 9) { 363 int rpm9 = rp>=0 ? rp%9 : rp%9+9; 364 int p10 = p10s[8-rpm9]; 365 uint32_t carry = 0; 366 for (k=a; k!=z; k++) { 367 uint32_t tmp = x[k] % p10; 368 x[k] = x[k]/p10 + carry; 369 carry = 1000000000/p10 * tmp; 370 if (k==a && !x[k]) { 371 a = (a+1 & MASK); 372 rp -= 9; 373 } 374 } 375 if (carry) x[z++] = carry; 376 rp += 9-rpm9; 377 } 378 379 /* Upscale until desired number of bits are left of radix point */ 380 while (rp < 9*LD_B1B_DIG || (rp == 9*LD_B1B_DIG && x[a]<th[0])) { 381 uint32_t carry = 0; 382 e2 -= 29; 383 for (k=(z-1 & MASK); ; k=(k-1 & MASK)) { 384 uint64_t tmp = ((uint64_t)x[k] << 29) + carry; 385 if (tmp > 1000000000) { 386 carry = tmp / 1000000000; 387 x[k] = tmp % 1000000000; 388 } else { 389 carry = 0; 390 x[k] = tmp; 391 } 392 if (k==(z-1 & MASK) && k!=a && !x[k]) z = k; 393 if (k==a) break; 394 } 395 if (carry) { 396 rp += 9; 397 a = (a-1 & MASK); 398 if (a == z) { 399 z = (z-1 & MASK); 400 x[z-1 & MASK] |= x[z]; 401 } 402 x[a] = carry; 403 } 404 } 405 406 /* Downscale until exactly number of bits are left of radix point */ 407 for (;;) { 408 uint32_t carry = 0; 409 int sh = 1; 410 for (i=0; i<LD_B1B_DIG; i++) { 411 k = (a+i & MASK); 412 if (k == z || x[k] < th[i]) { 413 i=LD_B1B_DIG; 414 break; 415 } 416 if (x[a+i & MASK] > th[i]) break; 417 } 418 if (i==LD_B1B_DIG && rp==9*LD_B1B_DIG) break; 419 /* FIXME: find a way to compute optimal sh */ 420 if (rp > 9+9*LD_B1B_DIG) sh = 9; 421 e2 += sh; 422 for (k=a; k!=z; k=(k+1 & MASK)) { 423 uint32_t tmp = x[k] & (1<<sh)-1; 424 x[k] = (x[k]>>sh) + carry; 425 carry = (1000000000>>sh) * tmp; 426 if (k==a && !x[k]) { 427 a = (a+1 & MASK); 428 i--; 429 rp -= 9; 430 } 431 } 432 if (carry) { 433 if ((z+1 & MASK) != a) { 434 x[z] = carry; 435 z = (z+1 & MASK); 436 } else x[z-1 & MASK] |= 1; 437 } 438 } 439 440 /* Assemble desired bits into floating point variable */ 441 for (y=i=0; i<LD_B1B_DIG; i++) { 442 if ((a+i & MASK)==z) x[(z=(z+1 & MASK))-1] = 0; 443 y = 1000000000.0L * y + x[a+i & MASK]; 444 } 445 446 y *= sign; 447 448 /* Limit precision for denormal results */ 449 if (bits > DBL_MANT_DIG+e2-emin) { 450 bits = DBL_MANT_DIG+e2-emin; 451 if (bits<0) bits=0; 452 denormal = 1; 453 } 454 455 /* Calculate bias term to force rounding, move out lower bits */ 456 if (bits < DBL_MANT_DIG) { 457 bias = copysign(scalbn(1, 2*DBL_MANT_DIG-bits-1), y); 458 frac = fmod(y, scalbn(1, DBL_MANT_DIG-bits)); 459 y -= frac; 460 y += bias; 461 } 462 463 /* Process tail of decimal input so it can affect rounding */ 464 if ((a+i & MASK) != z) { 465 uint32_t t = x[a+i & MASK]; 466 if (t < 500000000 && (t || (a+i+1 & MASK) != z)) 467 frac += 0.25*sign; 468 else if (t > 500000000) 469 frac += 0.75*sign; 470 else if (t == 500000000) { 471 if ((a+i+1 & MASK) == z) 472 frac += 0.5*sign; 473 else 474 frac += 0.75*sign; 475 } 476 if (DBL_MANT_DIG-bits >= 2 && !fmod(frac, 1)) 477 frac++; 478 } 479 480 y += frac; 481 y -= bias; 482 483 if ((e2+DBL_MANT_DIG & INT_MAX) > emax-5) { 484 if (fabs(y) >= pow(2, DBL_MANT_DIG)) { 485 if (denormal && bits==DBL_MANT_DIG+e2-emin) 486 denormal = 0; 487 y *= 0.5; 488 e2++; 489 } 490 if (e2+DBL_MANT_DIG>emax || (denormal && frac)) 491 errno = ERANGE; 492 } 493 494 return scalbn(y, e2); 495} 496 497static double hexfloat(FFFILE *f, int bits, int emin, int sign, int pok) 498{ 499 uint32_t x = 0; 500 double y = 0; 501 double scale = 1; 502 double bias = 0; 503 int gottail = 0, gotrad = 0, gotdig = 0; 504 long long rp = 0; 505 long long dc = 0; 506 long long e2 = 0; 507 int d; 508 int c; 509 510 c = shgetc(f); 511 512 /* Skip leading zeros */ 513 for (; c=='0'; c = shgetc(f)) 514 gotdig = 1; 515 516 if (c=='.') { 517 gotrad = 1; 518 c = shgetc(f); 519 /* Count zeros after the radix point before significand */ 520 for (rp=0; c=='0'; c = shgetc(f), rp--) gotdig = 1; 521 } 522 523 for (; c-'0'<10U || (c|32)-'a'<6U || c=='.'; c = shgetc(f)) { 524 if (c=='.') { 525 if (gotrad) break; 526 rp = dc; 527 gotrad = 1; 528 } else { 529 gotdig = 1; 530 if (c > '9') d = (c|32)+10-'a'; 531 else d = c-'0'; 532 if (dc<8) { 533 x = x*16 + d; 534 } else if (dc < DBL_MANT_DIG/4+1) { 535 y += d*(scale/=16); 536 } else if (d && !gottail) { 537 y += 0.5*scale; 538 gottail = 1; 539 } 540 dc++; 541 } 542 } 543 if (!gotdig) { 544 shunget(f); 545 if (pok) { 546 shunget(f); 547 if (gotrad) shunget(f); 548 } else { 549 shlim(f, 0); 550 } 551 return sign * 0.0; 552 } 553 if (!gotrad) rp = dc; 554 while (dc<8) x *= 16, dc++; 555 if ((c|32)=='p') { 556 e2 = scanexp(f, pok); 557 if (e2 == LLONG_MIN) { 558 if (pok) { 559 shunget(f); 560 } else { 561 shlim(f, 0); 562 return 0; 563 } 564 e2 = 0; 565 } 566 } else { 567 shunget(f); 568 } 569 e2 += 4*rp - 32; 570 571 if (!x) return sign * 0.0; 572 if (e2 > -emin) { 573 errno = ERANGE; 574 return sign * DBL_MAX * DBL_MAX; 575 } 576 if (e2 < emin-2*DBL_MANT_DIG) { 577 errno = ERANGE; 578 return sign * DBL_MIN * DBL_MIN; 579 } 580 581 while (x < 0x80000000) { 582 if (y>=0.5) { 583 x += x + 1; 584 y += y - 1; 585 } else { 586 x += x; 587 y += y; 588 } 589 e2--; 590 } 591 592 if (bits > 32+e2-emin) { 593 bits = 32+e2-emin; 594 if (bits<0) bits=0; 595 } 596 597 if (bits < DBL_MANT_DIG) 598 bias = copysign(scalbn(1, 32+DBL_MANT_DIG-bits-1), sign); 599 600 if (bits<32 && y && !(x&1)) x++, y=0; 601 602 y = bias + sign*(double)x + sign*y; 603 y -= bias; 604 605 if (!y) errno = ERANGE; 606 607 return scalbn(y, e2); 608} 609 610static double fffloatscan(FFFILE *f, int prec, int pok) 611{ 612 int sign = 1; 613 size_t i; 614 int bits; 615 int emin; 616 int c; 617 618 switch (prec) { 619 case 0: 620 bits = FLT_MANT_DIG; 621 emin = FLT_MIN_EXP-bits; 622 break; 623 case 1: 624 bits = DBL_MANT_DIG; 625 emin = DBL_MIN_EXP-bits; 626 break; 627 case 2: 628 bits = DBL_MANT_DIG; 629 emin = DBL_MIN_EXP-bits; 630 break; 631 default: 632 return 0; 633 } 634 635 while (av_isspace((c = shgetc(f)))); 636 637 if (c=='+' || c=='-') { 638 sign -= 2*(c=='-'); 639 c = shgetc(f); 640 } 641 642 for (i=0; i<8 && (c|32)=="infinity"[i]; i++) 643 if (i<7) c = shgetc(f); 644 if (i==3 || i==8 || (i>3 && pok)) { 645 if (i!=8) { 646 shunget(f); 647 if (pok) for (; i>3; i--) shunget(f); 648 } 649 return sign * INFINITY; 650 } 651 if (!i) for (i=0; i<3 && (c|32)=="nan"[i]; i++) 652 if (i<2) c = shgetc(f); 653 if (i==3) { 654 if (shgetc(f) != '(') { 655 shunget(f); 656 return NAN; 657 } 658 for (i=1; ; i++) { 659 c = shgetc(f); 660 if (c-'0'<10U || c-'A'<26U || c-'a'<26U || c=='_') 661 continue; 662 if (c==')') return NAN; 663 shunget(f); 664 if (!pok) { 665 errno = EINVAL; 666 shlim(f, 0); 667 return 0; 668 } 669 while (i--) shunget(f); 670 return NAN; 671 } 672 return NAN; 673 } 674 675 if (i) { 676 shunget(f); 677 errno = EINVAL; 678 shlim(f, 0); 679 return 0; 680 } 681 682 if (c=='0') { 683 c = shgetc(f); 684 if ((c|32) == 'x') 685 return hexfloat(f, bits, emin, sign, pok); 686 shunget(f); 687 c = '0'; 688 } 689 690 return decfloat(f, c, bits, emin, sign, pok); 691} 692 693static void *arg_n(va_list ap, unsigned int n) 694{ 695 void *p; 696 unsigned int i; 697 va_list ap2; 698 va_copy(ap2, ap); 699 for (i=n; i>1; i--) va_arg(ap2, void *); 700 p = va_arg(ap2, void *); 701 va_end(ap2); 702 return p; 703} 704 705static void store_int(void *dest, int size, unsigned long long i) 706{ 707 if (!dest) return; 708 switch (size) { 709 case SIZE_hh: 710 *(char *)dest = i; 711 break; 712 case SIZE_h: 713 *(short *)dest = i; 714 break; 715 case SIZE_def: 716 *(int *)dest = i; 717 break; 718 case SIZE_l: 719 *(long *)dest = i; 720 break; 721 case SIZE_ll: 722 *(long long *)dest = i; 723 break; 724 } 725} 726 727static int ff_vfscanf(FFFILE *f, const char *fmt, va_list ap) 728{ 729 int width; 730 int size; 731 int base; 732 const unsigned char *p; 733 int c, t; 734 char *s; 735 void *dest=NULL; 736 int invert; 737 int matches=0; 738 unsigned long long x; 739 double y; 740 ptrdiff_t pos = 0; 741 unsigned char scanset[257]; 742 size_t i; 743 744 for (p=(const unsigned char *)fmt; *p; p++) { 745 746 if (av_isspace(*p)) { 747 while (av_isspace(p[1])) p++; 748 shlim(f, 0); 749 while (av_isspace(shgetc(f))); 750 shunget(f); 751 pos += shcnt(f); 752 continue; 753 } 754 if (*p != '%' || p[1] == '%') { 755 shlim(f, 0); 756 if (*p == '%') { 757 p++; 758 while (av_isspace((c=shgetc(f)))); 759 } else { 760 c = shgetc(f); 761 } 762 if (c!=*p) { 763 shunget(f); 764 if (c<0) goto input_fail; 765 goto match_fail; 766 } 767 pos += shcnt(f); 768 continue; 769 } 770 771 p++; 772 if (*p=='*') { 773 dest = 0; p++; 774 } else if (av_isdigit(*p) && p[1]=='$') { 775 dest = arg_n(ap, *p-'0'); p+=2; 776 } else { 777 dest = va_arg(ap, void *); 778 } 779 780 for (width=0; av_isdigit(*p); p++) { 781 width = 10*width + *p - '0'; 782 } 783 784 if (*p=='m') { 785 s = 0; 786 p++; 787 } 788 789 size = SIZE_def; 790 switch (*p++) { 791 case 'h': 792 if (*p == 'h') p++, size = SIZE_hh; 793 else size = SIZE_h; 794 break; 795 case 'l': 796 if (*p == 'l') p++, size = SIZE_ll; 797 else size = SIZE_l; 798 break; 799 case 'j': 800 size = SIZE_ll; 801 break; 802 case 'z': 803 case 't': 804 size = SIZE_l; 805 break; 806 case 'L': 807 size = SIZE_L; 808 break; 809 case 'd': case 'i': case 'o': case 'u': case 'x': 810 case 'a': case 'e': case 'f': case 'g': 811 case 'A': case 'E': case 'F': case 'G': case 'X': 812 case 's': case 'c': case '[': 813 case 'S': case 'C': 814 case 'p': case 'n': 815 p--; 816 break; 817 default: 818 goto fmt_fail; 819 } 820 821 t = *p; 822 823 /* C or S */ 824 if ((t&0x2f) == 3) { 825 t |= 32; 826 size = SIZE_l; 827 } 828 829 switch (t) { 830 case 'c': 831 if (width < 1) width = 1; 832 case '[': 833 break; 834 case 'n': 835 store_int(dest, size, pos); 836 /* do not increment match count, etc! */ 837 continue; 838 default: 839 shlim(f, 0); 840 while (av_isspace(shgetc(f))); 841 shunget(f); 842 pos += shcnt(f); 843 } 844 845 shlim(f, width); 846 if (shgetc(f) < 0) goto input_fail; 847 shunget(f); 848 849 switch (t) { 850 case 's': 851 case 'c': 852 case '[': 853 if (t == 'c' || t == 's') { 854 memset(scanset, -1, sizeof scanset); 855 scanset[0] = 0; 856 if (t == 's') { 857 scanset[1 + '\t'] = 0; 858 scanset[1 + '\n'] = 0; 859 scanset[1 + '\v'] = 0; 860 scanset[1 + '\f'] = 0; 861 scanset[1 + '\r'] = 0; 862 scanset[1 + ' ' ] = 0; 863 } 864 } else { 865 if (*++p == '^') p++, invert = 1; 866 else invert = 0; 867 memset(scanset, invert, sizeof scanset); 868 scanset[0] = 0; 869 if (*p == '-') p++, scanset[1+'-'] = 1-invert; 870 else if (*p == ']') p++, scanset[1+']'] = 1-invert; 871 for (; *p != ']'; p++) { 872 if (!*p) goto fmt_fail; 873 if (*p=='-' && p[1] && p[1] != ']') 874 for (c=p++[-1]; c<*p; c++) 875 scanset[1+c] = 1-invert; 876 scanset[1+*p] = 1-invert; 877 } 878 } 879 s = 0; 880 i = 0; 881 if ((s = dest)) { 882 while (scanset[(c=shgetc(f))+1]) 883 s[i++] = c; 884 } else { 885 while (scanset[(c=shgetc(f))+1]); 886 } 887 shunget(f); 888 if (!shcnt(f)) goto match_fail; 889 if (t == 'c' && shcnt(f) != width) goto match_fail; 890 if (t != 'c') { 891 if (s) s[i] = 0; 892 } 893 break; 894 case 'p': 895 case 'X': 896 case 'x': 897 base = 16; 898 goto int_common; 899 case 'o': 900 base = 8; 901 goto int_common; 902 case 'd': 903 case 'u': 904 base = 10; 905 goto int_common; 906 case 'i': 907 base = 0; 908int_common: 909 x = ffintscan(f, base, 0, ULLONG_MAX); 910 if (!shcnt(f)) 911 goto match_fail; 912 if (t=='p' && dest) 913 *(void **)dest = (void *)(uintptr_t)x; 914 else 915 store_int(dest, size, x); 916 break; 917 case 'a': case 'A': 918 case 'e': case 'E': 919 case 'f': case 'F': 920 case 'g': case 'G': 921 y = fffloatscan(f, size, 0); 922 if (!shcnt(f)) 923 goto match_fail; 924 if (dest) { 925 switch (size) { 926 case SIZE_def: 927 *(float *)dest = y; 928 break; 929 case SIZE_l: 930 *(double *)dest = y; 931 break; 932 case SIZE_L: 933 *(double *)dest = y; 934 break; 935 } 936 } 937 break; 938 } 939 940 pos += shcnt(f); 941 if (dest) matches++; 942 } 943 if (0) { 944fmt_fail: 945input_fail: 946 if (!matches) matches--; 947 } 948match_fail: 949 return matches; 950} 951 952static int ff_vsscanf(const char *s, const char *fmt, va_list ap) 953{ 954 FFFILE f = { 955 .buf = (void *)s, .cookie = (void *)s, 956 .read = ffstring_read, 957 }; 958 959 return ff_vfscanf(&f, fmt, ap); 960} 961 962int av_sscanf(const char *string, const char *format, ...) 963{ 964 int ret; 965 va_list ap; 966 va_start(ap, format); 967 ret = ff_vsscanf(string, format, ap); 968 va_end(ap); 969 return ret; 970} 971