2 * Copyright (c) 2005-2014 Rich Felker, et al.
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:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
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.
37 typedef struct FFFILE
{
40 unsigned char *rpos
, *rend
;
42 ptrdiff_t shlim
, shcnt
;
44 size_t (*read
)(struct FFFILE
*, unsigned char *, size_t);
54 #define shcnt(f) ((f)->shcnt + ((f)->rpos - (f)->buf))
56 static int fftoread(FFFILE
*f
)
58 f
->rpos
= f
->rend
= f
->buf
+ f
->buf_size
;
62 static size_t ffstring_read(FFFILE
*f
, unsigned char *buf
, size_t len
)
64 char *src
= f
->cookie
;
66 char *end
= memchr(src
, 0, k
);
70 memcpy(buf
, src
, len
);
71 f
->rpos
= (void *)(src
+len
);
72 f
->rend
= (void *)(src
+k
);
78 static int ffuflow(FFFILE
*f
)
81 if (!fftoread(f
) && f
->read(f
, &c
, 1)==1) return c
;
85 static void ffshlim(FFFILE
*f
, ptrdiff_t 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
;
96 static int ffshgetc(FFFILE
*f
)
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
;
106 if (f
->shlim
&& f
->rend
- f
->rpos
> f
->shlim
- cnt
)
107 f
->shend
= f
->rpos
+ (f
->shlim
- cnt
);
110 f
->shcnt
= f
->buf
- f
->rpos
+ cnt
;
111 if (f
->rpos
[-1] != c
) f
->rpos
[-1] = c
;
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)
119 static 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,
138 static unsigned long long ffintscan(FFFILE
*f
, unsigned base
, int pok
, unsigned long long lim
)
140 const unsigned char *val
= table
+1;
143 unsigned long long y
;
144 if (base
> 36 || base
== 1) {
148 while (av_isspace((c
=shgetc(f
))));
149 if (c
=='+' || c
=='-') {
153 if ((base
== 0 || base
== 16) && c
=='0') {
164 } else if (base
== 0) {
168 if (base
== 0) base
= 10;
169 if (val
[c
] >= base
) {
177 for (x
=0; c
-'0'<10U && x
<=UINT_MAX
/10-1; c
=shgetc(f
))
179 for (y
=x
; c
-'0'<10U && y
<=ULLONG_MAX
/10 && 10*y
<=ULLONG_MAX
-(c
-'0'); c
=shgetc(f
))
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
))
186 for (y
=x
; val
[c
]<base
&& y
<=ULLONG_MAX
>>bs
; c
=shgetc(f
))
189 for (x
=0; val
[c
]<base
&& x
<=UINT_MAX
/36-1; c
=shgetc(f
))
191 for (y
=x
; val
[c
]<base
&& y
<=ULLONG_MAX
/base
&& base
*y
<=ULLONG_MAX
-val
[c
]; c
=shgetc(f
))
195 for (; val
[c
]<base
; c
=shgetc(f
));
203 if (!(lim
&1) && !neg
) {
214 static long long scanexp(FFFILE
*f
, int pok
)
222 if (c
=='+' || c
=='-') {
225 if (c
-'0'>=10U && pok
) shunget(f
);
231 for (x
=0; c
-'0'<10U && x
<INT_MAX
/10; c
= shgetc(f
))
233 for (y
=x
; c
-'0'<10U && y
<LLONG_MAX
/100; c
= shgetc(f
))
235 for (; c
-'0'<10U; c
= shgetc(f
));
241 #define LD_B1B_MAX 9007199, 254740991
243 #define MASK (KMAX-1)
245 static double decfloat(FFFILE
*f
, int c
, int bits
, int emin
, int sign
, int pok
)
248 static const uint32_t th
[] = { LD_B1B_MAX
};
250 long long lrp
=0, dc
=0;
253 int gotdig
= 0, gotrad
= 0;
256 int emax
= -emin
-bits
+3;
261 static const int p10s
[] = { 10, 100, 1000, 10000,
262 100000, 1000000, 10000000, 100000000 };
267 /* Don't let leading zeros consume buffer space */
268 for (; c
=='0'; c
= shgetc(f
)) gotdig
=1;
271 for (c
= shgetc(f
); c
=='0'; c
= shgetc(f
)) gotdig
=1, lrp
--;
275 for (; c
-'0'<10U || c
=='.'; c
= shgetc(f
)) {
280 } else if (k
< KMAX
-3) {
282 if (c
!='0') lnz
= dc
;
283 if (j
) x
[k
] = x
[k
]*10 + c
-'0';
300 if (gotdig
&& (c
|32)=='e') {
301 e10
= scanexp(f
, pok
);
302 if (e10
== LLONG_MIN
) {
321 /* Handle zero specially to avoid nasty special cases later */
322 if (!x
[0]) return sign
* 0.0;
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];
329 return sign
* DBL_MAX
* DBL_MAX
;
331 if (lrp
< emin
-2*DBL_MANT_DIG
) {
333 return sign
* DBL_MIN
* DBL_MIN
;
336 /* Align incomplete final B1B digit */
338 for (; j
<9; j
++) x
[k
]*=10;
348 /* Optimize small to mid-size integers (even in exp. notation) */
349 if (lnz
<9 && lnz
<=rp
&& rp
< 18) {
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];
358 /* Drop trailing zeros */
359 for (; !x
[z
-1]; z
--);
361 /* Align radix point to B1B digit boundary */
363 int rpm9
= rp
>=0 ? rp
%9 : rp
%9+9;
364 int p10
= p10s
[8-rpm9
];
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
;
375 if (carry
) x
[z
++] = carry
;
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])) {
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;
392 if (k
==(z
-1 & MASK
) && k
!=a
&& !x
[k
]) z
= k
;
400 x
[z
-1 & MASK
] |= x
[z
];
406 /* Downscale until exactly number of bits are left of radix point */
410 for (i
=0; i
<LD_B1B_DIG
; i
++) {
412 if (k
== z
|| x
[k
] < th
[i
]) {
416 if (x
[a
+i
& MASK
] > th
[i
]) break;
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;
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
;
433 if ((z
+1 & MASK
) != a
) {
436 } else x
[z
-1 & MASK
] |= 1;
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
];
448 /* Limit precision for denormal results */
449 if (bits
> DBL_MANT_DIG
+e2
-emin
) {
450 bits
= DBL_MANT_DIG
+e2
-emin
;
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
));
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
))
468 else if (t
> 500000000)
470 else if (t
== 500000000) {
471 if ((a
+i
+1 & MASK
) == z
)
476 if (DBL_MANT_DIG
-bits
>= 2 && !fmod(frac
, 1))
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
)
490 if (e2
+DBL_MANT_DIG
>emax
|| (denormal
&& frac
))
494 return scalbn(y
, e2
);
497 static double hexfloat(FFFILE
*f
, int bits
, int emin
, int sign
, int pok
)
503 int gottail
= 0, gotrad
= 0, gotdig
= 0;
512 /* Skip leading zeros */
513 for (; c
=='0'; c
= shgetc(f
))
519 /* Count zeros after the radix point before significand */
520 for (rp
=0; c
=='0'; c
= shgetc(f
), rp
--) gotdig
= 1;
523 for (; c
-'0'<10U || (c
|32)-'a'<6U || c
=='.'; c
= shgetc(f
)) {
530 if (c
> '9') d
= (c
|32)+10-'a';
534 } else if (dc
< DBL_MANT_DIG
/4+1) {
536 } else if (d
&& !gottail
) {
547 if (gotrad
) shunget(f
);
553 if (!gotrad
) rp
= dc
;
554 while (dc
<8) x
*= 16, dc
++;
556 e2
= scanexp(f
, pok
);
557 if (e2
== LLONG_MIN
) {
571 if (!x
) return sign
* 0.0;
574 return sign
* DBL_MAX
* DBL_MAX
;
576 if (e2
< emin
-2*DBL_MANT_DIG
) {
578 return sign
* DBL_MIN
* DBL_MIN
;
581 while (x
< 0x80000000) {
592 if (bits
> 32+e2
-emin
) {
597 if (bits
< DBL_MANT_DIG
)
598 bias
= copysign(scalbn(1, 32+DBL_MANT_DIG
-bits
-1), sign
);
600 if (bits
<32 && y
&& !(x
&1)) x
++, y
=0;
602 y
= bias
+ sign
*(double)x
+ sign
*y
;
605 if (!y
) errno
= ERANGE
;
607 return scalbn(y
, e2
);
610 static double fffloatscan(FFFILE
*f
, int prec
, int pok
)
621 emin
= FLT_MIN_EXP
-bits
;
625 emin
= DBL_MIN_EXP
-bits
;
629 emin
= DBL_MIN_EXP
-bits
;
635 while (av_isspace((c
= shgetc(f
))));
637 if (c
=='+' || c
=='-') {
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
)) {
647 if (pok
) for (; i
>3; i
--) shunget(f
);
649 return sign
* INFINITY
;
651 if (!i
) for (i
=0; i
<3 && (c
|32)=="nan"[i
]; i
++)
652 if (i
<2) c
= shgetc(f
);
654 if (shgetc(f
) != '(') {
660 if (c
-'0'<10U || c
-'A'<26U || c
-'a'<26U || c
=='_')
662 if (c
==')') return NAN
;
669 while (i
--) shunget(f
);
684 return hexfloat(f
, bits
, emin
, sign
, pok
);
689 return decfloat(f
, c
, bits
, emin
, sign
, pok
);
692 static void *arg_n(va_list ap
, unsigned int n
)
698 for (i
=n
; i
>1; i
--) va_arg(ap2
, void *);
699 p
= va_arg(ap2
, void *);
704 static void store_int(void *dest
, int size
, unsigned long long i
)
721 *(long long *)dest
= i
;
726 static int ff_vfscanf(FFFILE
*f
, const char *fmt
, va_list ap
)
731 const unsigned char *p
;
737 unsigned long long x
;
740 unsigned char scanset
[257];
743 for (p
=(const unsigned char *)fmt
; *p
; p
++) {
745 if (av_isspace(*p
)) {
746 while (av_isspace(p
[1])) p
++;
748 while (av_isspace(shgetc(f
)));
753 if (*p
!= '%' || p
[1] == '%') {
757 while (av_isspace((c
=shgetc(f
))));
763 if (c
<0) goto input_fail
;
773 } else if (av_isdigit(*p
) && p
[1]=='$') {
774 dest
= arg_n(ap
, *p
-'0'); p
+=2;
776 dest
= va_arg(ap
, void *);
779 for (width
=0; av_isdigit(*p
); p
++) {
780 width
= 10*width
+ *p
- '0';
791 if (*p
== 'h') p
++, size
= SIZE_hh
;
795 if (*p
== 'l') p
++, size
= SIZE_ll
;
808 case 'd': case 'i': case 'o': case 'u': case 'x':
809 case 'a': case 'e': case 'f': case 'g':
810 case 'A': case 'E': case 'F': case 'G': case 'X':
811 case 's': case 'c': case '[':
830 if (width
< 1) width
= 1;
834 store_int(dest
, size
, pos
);
835 /* do not increment match count, etc! */
839 while (av_isspace(shgetc(f
)));
845 if (shgetc(f
) < 0) goto input_fail
;
852 if (t
== 'c' || t
== 's') {
853 memset(scanset
, -1, sizeof scanset
);
856 scanset
[1 + '\t'] = 0;
857 scanset
[1 + '\n'] = 0;
858 scanset
[1 + '\v'] = 0;
859 scanset
[1 + '\f'] = 0;
860 scanset
[1 + '\r'] = 0;
861 scanset
[1 + ' ' ] = 0;
864 if (*++p
== '^') p
++, invert
= 1;
866 memset(scanset
, invert
, sizeof scanset
);
868 if (*p
== '-') p
++, scanset
[1+'-'] = 1-invert
;
869 else if (*p
== ']') p
++, scanset
[1+']'] = 1-invert
;
870 for (; *p
!= ']'; p
++) {
871 if (!*p
) goto fmt_fail
;
872 if (*p
=='-' && p
[1] && p
[1] != ']')
873 for (c
=p
++[-1]; c
<*p
; c
++)
874 scanset
[1+c
] = 1-invert
;
875 scanset
[1+*p
] = 1-invert
;
881 while (scanset
[(c
=shgetc(f
))+1])
884 while (scanset
[(c
=shgetc(f
))+1]);
887 if (!shcnt(f
)) goto match_fail
;
888 if (t
== 'c' && shcnt(f
) != width
) goto match_fail
;
908 x
= ffintscan(f
, base
, 0, ULLONG_MAX
);
912 *(void **)dest
= (void *)(uintptr_t)x
;
914 store_int(dest
, size
, x
);
920 y
= fffloatscan(f
, size
, 0);
945 if (!matches
) matches
--;
951 static int ff_vsscanf(const char *s
, const char *fmt
, va_list ap
)
954 .buf
= (void *)s
, .cookie
= (void *)s
,
955 .read
= ffstring_read
,
958 return ff_vfscanf(&f
, fmt
, ap
);
961 int av_sscanf(const char *string
, const char *format
, ...)
965 va_start(ap
, format
);
966 ret
= ff_vsscanf(string
, format
, ap
);