Line | Branch | Exec | Source |
---|---|---|---|
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 | |||
37 | typedef 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 | |||
56 | 9461 | static int fftoread(FFFILE *f) | |
57 | { | ||
58 | 9461 | f->rpos = f->rend = f->buf + f->buf_size; | |
59 | 9461 | return 0; | |
60 | } | ||
61 | |||
62 | 9461 | static size_t ffstring_read(FFFILE *f, unsigned char *buf, size_t len) | |
63 | { | ||
64 | 9461 | char *src = f->cookie; | |
65 | 9461 | size_t k = len+256; | |
66 | 9461 | char *end = memchr(src, 0, k); | |
67 | |||
68 |
2/2✓ Branch 0 taken 9455 times.
✓ Branch 1 taken 6 times.
|
9461 | if (end) k = end-src; |
69 |
2/2✓ Branch 0 taken 147 times.
✓ Branch 1 taken 9314 times.
|
9461 | if (k < len) len = k; |
70 | 9461 | memcpy(buf, src, len); | |
71 | 9461 | f->rpos = (void *)(src+len); | |
72 | 9461 | f->rend = (void *)(src+k); | |
73 | 9461 | f->cookie = src+k; | |
74 | |||
75 | 9461 | return len; | |
76 | } | ||
77 | |||
78 | 9461 | static int ffuflow(FFFILE *f) | |
79 | { | ||
80 | unsigned char c; | ||
81 |
3/4✓ Branch 1 taken 9461 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9314 times.
✓ Branch 5 taken 147 times.
|
9461 | if (!fftoread(f) && f->read(f, &c, 1)==1) return c; |
82 | 147 | return EOF; | |
83 | } | ||
84 | |||
85 | 40683 | static void ffshlim(FFFILE *f, ptrdiff_t lim) | |
86 | { | ||
87 | 40683 | f->shlim = lim; | |
88 | 40683 | f->shcnt = f->buf - f->rpos; | |
89 | /* If lim is nonzero, rend must be a valid pointer. */ | ||
90 |
4/4✓ Branch 0 taken 34177 times.
✓ Branch 1 taken 6506 times.
✓ Branch 2 taken 17088 times.
✓ Branch 3 taken 17089 times.
|
40683 | if (lim && f->rend - f->rpos > lim) |
91 | 17088 | f->shend = f->rpos + lim; | |
92 | else | ||
93 | 23595 | f->shend = f->rend; | |
94 | 40683 | } | |
95 | |||
96 | 43637 | static int ffshgetc(FFFILE *f) | |
97 | { | ||
98 | int c; | ||
99 | 43637 | ptrdiff_t cnt = shcnt(f); | |
100 |
6/6✓ Branch 0 taken 42721 times.
✓ Branch 1 taken 916 times.
✓ Branch 2 taken 8545 times.
✓ Branch 3 taken 34176 times.
✓ Branch 5 taken 147 times.
✓ Branch 6 taken 9314 times.
|
43637 | if (f->shlim && cnt >= f->shlim || (c=ffuflow(f)) < 0) { |
101 | 34323 | f->shcnt = f->buf - f->rpos + cnt; | |
102 | 34323 | f->shend = 0; | |
103 | 34323 | return EOF; | |
104 | } | ||
105 | 9314 | cnt++; | |
106 |
3/4✓ Branch 0 taken 8544 times.
✓ Branch 1 taken 770 times.
✓ Branch 2 taken 8544 times.
✗ Branch 3 not taken.
|
9314 | if (f->shlim && f->rend - f->rpos > f->shlim - cnt) |
107 | 8544 | f->shend = f->rpos + (f->shlim - cnt); | |
108 | else | ||
109 | 770 | f->shend = f->rend; | |
110 | 9314 | f->shcnt = f->buf - f->rpos + cnt; | |
111 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9314 times.
|
9314 | if (f->rpos[-1] != c) f->rpos[-1] = c; |
112 | 9314 | 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 | |||
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, | ||
136 | }; | ||
137 | |||
138 | 2133 | static unsigned long long ffintscan(FFFILE *f, unsigned base, int pok, unsigned long long lim) | |
139 | { | ||
140 | 2133 | const unsigned char *val = table+1; | |
141 | 2133 | int c, neg=0; | |
142 | unsigned x; | ||
143 | unsigned long long y; | ||
144 |
2/4✓ Branch 0 taken 2133 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2133 times.
|
2133 | if (base > 36 || base == 1) { |
145 | ✗ | errno = EINVAL; | |
146 | ✗ | return 0; | |
147 | } | ||
148 |
2/4✓ Branch 0 taken 2133 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2133 times.
|
2133 | while (av_isspace((c=shgetc(f)))); |
149 |
3/4✓ Branch 0 taken 2133 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2130 times.
|
2133 | if (c=='+' || c=='-') { |
150 | 3 | neg = -(c=='-'); | |
151 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | c = shgetc(f); |
152 | } | ||
153 |
2/6✓ Branch 0 taken 2133 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2133 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
2133 | 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 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2133 times.
|
2133 | if (base == 0) base = 10; |
169 |
2/2✓ Branch 0 taken 73 times.
✓ Branch 1 taken 2060 times.
|
2133 | if (val[c] >= base) { |
170 |
1/2✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
|
73 | shunget(f); |
171 | 73 | shlim(f, 0); | |
172 | 73 | errno = EINVAL; | |
173 | 73 | return 0; | |
174 | } | ||
175 | } | ||
176 |
1/2✓ Branch 0 taken 2060 times.
✗ Branch 1 not taken.
|
2060 | if (base == 10) { |
177 |
3/4✓ Branch 1 taken 3736 times.
✓ Branch 2 taken 2060 times.
✓ Branch 3 taken 3736 times.
✗ Branch 4 not taken.
|
5796 | for (x=0; c-'0'<10U && x<=UINT_MAX/10-1; c=shgetc(f)) |
178 |
2/2✓ Branch 0 taken 3706 times.
✓ Branch 1 taken 30 times.
|
3736 | x = x*10 + (c-'0'); |
179 |
1/6✗ Branch 1 not taken.
✓ Branch 2 taken 2060 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
2060 | 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 |
1/2✓ Branch 0 taken 2060 times.
✗ Branch 1 not taken.
|
2060 | 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 | } | ||
200 | ✗ | done: | |
201 |
2/2✓ Branch 0 taken 2030 times.
✓ Branch 1 taken 30 times.
|
2060 | shunget(f); |
202 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2060 times.
|
2060 | 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 | 2060 | return (y^neg)-neg; | |
212 | } | ||
213 | |||
214 | ✗ | static 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 | |||
245 | 61 | static 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 | 61 | long long lrp=0, dc=0; | |
251 | 61 | long long e10=0; | |
252 | 61 | int lnz = 0; | |
253 | 61 | int gotdig = 0, gotrad = 0; | |
254 | int rp; | ||
255 | int e2; | ||
256 | 61 | int emax = -emin-bits+3; | |
257 | 61 | int denormal = 0; | |
258 | double y; | ||
259 | 61 | double frac=0; | |
260 | 61 | double bias=0; | |
261 | static const int p10s[] = { 10, 100, 1000, 10000, | ||
262 | 100000, 1000000, 10000000, 100000000 }; | ||
263 | |||
264 | 61 | j=0; | |
265 | 61 | k=0; | |
266 | |||
267 | /* Don't let leading zeros consume buffer space */ | ||
268 |
3/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 61 times.
|
63 | for (; c=='0'; c = shgetc(f)) gotdig=1; |
269 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 59 times.
|
61 | if (c=='.') { |
270 | 2 | gotrad = 1; | |
271 |
2/6✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
|
2 | for (c = shgetc(f); c=='0'; c = shgetc(f)) gotdig=1, lrp--; |
272 | } | ||
273 | |||
274 | 61 | x[0] = 0; | |
275 |
6/6✓ Branch 0 taken 395 times.
✓ Branch 1 taken 61 times.
✓ Branch 3 taken 400 times.
✓ Branch 4 taken 117 times.
✓ Branch 5 taken 56 times.
✓ Branch 6 taken 61 times.
|
517 | for (; c-'0'<10U || c=='.'; c = shgetc(f)) { |
276 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 400 times.
|
456 | if (c == '.') { |
277 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
|
56 | if (gotrad) break; |
278 | 56 | gotrad = 1; | |
279 | 56 | lrp = dc; | |
280 |
1/2✓ Branch 0 taken 400 times.
✗ Branch 1 not taken.
|
400 | } else if (k < KMAX-3) { |
281 | 400 | dc++; | |
282 |
2/2✓ Branch 0 taken 64 times.
✓ Branch 1 taken 336 times.
|
400 | if (c!='0') lnz = dc; |
283 |
2/2✓ Branch 0 taken 339 times.
✓ Branch 1 taken 61 times.
|
400 | if (j) x[k] = x[k]*10 + c-'0'; |
284 | 61 | else x[k] = c-'0'; | |
285 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 400 times.
|
400 | if (++j==9) { |
286 | ✗ | k++; | |
287 | ✗ | j=0; | |
288 | } | ||
289 | 400 | gotdig=1; | |
290 | } else { | ||
291 | ✗ | dc++; | |
292 | ✗ | if (c!='0') { | |
293 | ✗ | lnz = (KMAX-4)*9; | |
294 | ✗ | x[KMAX-4] |= 1; | |
295 | } | ||
296 | } | ||
297 | } | ||
298 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 58 times.
|
61 | if (!gotrad) lrp=dc; |
299 | |||
300 |
2/4✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 61 times.
|
61 | 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 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
|
61 | } else if (c>=0) { |
313 | ✗ | shunget(f); | |
314 | } | ||
315 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
|
61 | 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 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
|
61 | if (!x[0]) return sign * 0.0; |
323 | |||
324 | /* Optimize small integers (w/no exponent) and over/under-flow */ | ||
325 |
5/8✓ Branch 0 taken 3 times.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
|
61 | if (lrp==dc && dc<10 && (bits>30 || x[0]>>bits==0)) |
326 | 3 | return sign * (double)x[0]; | |
327 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
|
58 | if (lrp > -emin/2) { |
328 | ✗ | errno = ERANGE; | |
329 | ✗ | return sign * DBL_MAX * DBL_MAX; | |
330 | } | ||
331 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
|
58 | 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 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | if (j) { |
338 |
2/2✓ Branch 0 taken 128 times.
✓ Branch 1 taken 58 times.
|
186 | for (; j<9; j++) x[k]*=10; |
339 | 58 | k++; | |
340 | 58 | j=0; | |
341 | } | ||
342 | |||
343 | 58 | a = 0; | |
344 | 58 | z = k; | |
345 | 58 | e2 = 0; | |
346 | 58 | rp = lrp; | |
347 | |||
348 | /* Optimize small to mid-size integers (even in exp. notation) */ | ||
349 |
4/6✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
|
58 | if (lnz<9 && lnz<=rp && rp < 18) { |
350 | int bitlim; | ||
351 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
|
56 | if (rp == 9) return sign * (double)x[0]; |
352 |
1/2✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
|
56 | 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 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | for (; !x[z-1]; z--); |
360 | |||
361 | /* Align radix point to B1B digit boundary */ | ||
362 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | 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 |
4/6✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
6 | while (rp < 9*LD_B1B_DIG || (rp == 9*LD_B1B_DIG && x[a]<th[0])) { |
381 | 4 | uint32_t carry = 0; | |
382 | 4 | e2 -= 29; | |
383 | 6 | for (k=(z-1 & MASK); ; k=(k-1 & MASK)) { | |
384 | 6 | uint64_t tmp = ((uint64_t)x[k] << 29) + carry; | |
385 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
|
6 | if (tmp > 1000000000) { |
386 | 4 | carry = tmp / 1000000000; | |
387 | 4 | x[k] = tmp % 1000000000; | |
388 | } else { | ||
389 | 2 | carry = 0; | |
390 | 2 | x[k] = tmp; | |
391 | } | ||
392 |
4/6✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
6 | if (k==(z-1 & MASK) && k!=a && !x[k]) z = k; |
393 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
|
6 | if (k==a) break; |
394 | } | ||
395 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (carry) { |
396 | 4 | rp += 9; | |
397 | 4 | a = (a-1 & MASK); | |
398 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (a == z) { |
399 | ✗ | z = (z-1 & MASK); | |
400 | ✗ | x[z-1 & MASK] |= x[z]; | |
401 | } | ||
402 | 4 | x[a] = carry; | |
403 | } | ||
404 | } | ||
405 | |||
406 | /* Downscale until exactly number of bits are left of radix point */ | ||
407 | 10 | for (;;) { | |
408 | 12 | uint32_t carry = 0; | |
409 | 12 | int sh = 1; | |
410 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | for (i=0; i<LD_B1B_DIG; i++) { |
411 | 14 | k = (a+i & MASK); | |
412 |
3/4✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 12 times.
|
14 | if (k == z || x[k] < th[i]) { |
413 | 2 | i=LD_B1B_DIG; | |
414 | 2 | break; | |
415 | } | ||
416 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
|
12 | if (x[a+i & MASK] > th[i]) break; |
417 | } | ||
418 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
12 | if (i==LD_B1B_DIG && rp==9*LD_B1B_DIG) break; |
419 | /* FIXME: find a way to compute optimal sh */ | ||
420 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (rp > 9+9*LD_B1B_DIG) sh = 9; |
421 | 10 | e2 += sh; | |
422 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
|
30 | for (k=a; k!=z; k=(k+1 & MASK)) { |
423 | 20 | uint32_t tmp = x[k] & (1<<sh)-1; | |
424 | 20 | x[k] = (x[k]>>sh) + carry; | |
425 | 20 | carry = (1000000000>>sh) * tmp; | |
426 |
3/4✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
|
20 | if (k==a && !x[k]) { |
427 | ✗ | a = (a+1 & MASK); | |
428 | ✗ | i--; | |
429 | ✗ | rp -= 9; | |
430 | } | ||
431 | } | ||
432 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | 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 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
|
6 | for (y=i=0; i<LD_B1B_DIG; i++) { |
442 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if ((a+i & MASK)==z) x[(z=(z+1 & MASK))-1] = 0; |
443 | 4 | y = 1000000000.0L * y + x[a+i & MASK]; | |
444 | } | ||
445 | |||
446 | 2 | y *= sign; | |
447 | |||
448 | /* Limit precision for denormal results */ | ||
449 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | 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 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (bits < DBL_MANT_DIG) { |
457 | 2 | bias = copysign(scalbn(1, 2*DBL_MANT_DIG-bits-1), y); | |
458 | 2 | frac = fmod(y, scalbn(1, DBL_MANT_DIG-bits)); | |
459 | 2 | y -= frac; | |
460 | 2 | y += bias; | |
461 | } | ||
462 | |||
463 | /* Process tail of decimal input so it can affect rounding */ | ||
464 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | 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 | 2 | y += frac; | |
481 | 2 | y -= bias; | |
482 | |||
483 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | 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 | 2 | return scalbn(y, e2); | |
495 | } | ||
496 | |||
497 | ✗ | static 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 | |||
610 | 61 | static double fffloatscan(FFFILE *f, int prec, int pok) | |
611 | { | ||
612 | 61 | int sign = 1; | |
613 | size_t i; | ||
614 | int bits; | ||
615 | int emin; | ||
616 | int c; | ||
617 | |||
618 |
1/4✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
61 | switch (prec) { |
619 | 61 | case 0: | |
620 | 61 | bits = FLT_MANT_DIG; | |
621 | 61 | emin = FLT_MIN_EXP-bits; | |
622 | 61 | 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 |
2/4✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 61 times.
|
61 | while (av_isspace((c = shgetc(f)))); |
636 | |||
637 |
3/4✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 33 times.
|
61 | if (c=='+' || c=='-') { |
638 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | sign -= 2*(c=='-'); |
639 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | c = shgetc(f); |
640 | } | ||
641 | |||
642 |
2/4✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 61 times.
|
61 | for (i=0; i<8 && (c|32)=="infinity"[i]; i++) |
643 | ✗ | if (i<7) c = shgetc(f); | |
644 |
3/8✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 61 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
61 | 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 |
3/6✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 61 times.
|
61 | if (!i) for (i=0; i<3 && (c|32)=="nan"[i]; i++) |
652 | ✗ | if (i<2) c = shgetc(f); | |
653 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
|
61 | 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 | } | ||
673 | |||
674 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
|
61 | if (i) { |
675 | ✗ | shunget(f); | |
676 | ✗ | errno = EINVAL; | |
677 | ✗ | shlim(f, 0); | |
678 | ✗ | return 0; | |
679 | } | ||
680 | |||
681 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 59 times.
|
61 | if (c=='0') { |
682 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | c = shgetc(f); |
683 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if ((c|32) == 'x') |
684 | ✗ | return hexfloat(f, bits, emin, sign, pok); | |
685 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | shunget(f); |
686 | 2 | c = '0'; | |
687 | } | ||
688 | |||
689 | 61 | return decfloat(f, c, bits, emin, sign, pok); | |
690 | } | ||
691 | |||
692 | ✗ | static void *arg_n(va_list ap, unsigned int n) | |
693 | { | ||
694 | void *p; | ||
695 | unsigned int i; | ||
696 | va_list ap2; | ||
697 | ✗ | va_copy(ap2, ap); | |
698 | ✗ | for (i=n; i>1; i--) va_arg(ap2, void *); | |
699 | ✗ | p = va_arg(ap2, void *); | |
700 | ✗ | va_end(ap2); | |
701 | ✗ | return p; | |
702 | } | ||
703 | |||
704 | 2111 | static void store_int(void *dest, int size, unsigned long long i) | |
705 | { | ||
706 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2111 times.
|
2111 | if (!dest) return; |
707 |
3/6✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1833 times.
✓ Branch 3 taken 227 times.
✓ Branch 4 taken 51 times.
✗ Branch 5 not taken.
|
2111 | switch (size) { |
708 | ✗ | case SIZE_hh: | |
709 | ✗ | *(char *)dest = i; | |
710 | ✗ | break; | |
711 | ✗ | case SIZE_h: | |
712 | ✗ | *(short *)dest = i; | |
713 | ✗ | break; | |
714 | 1833 | case SIZE_def: | |
715 | 1833 | *(int *)dest = i; | |
716 | 1833 | break; | |
717 | 227 | case SIZE_l: | |
718 | 227 | *(long *)dest = i; | |
719 | 227 | break; | |
720 | 51 | case SIZE_ll: | |
721 | 51 | *(long long *)dest = i; | |
722 | 51 | break; | |
723 | } | ||
724 | } | ||
725 | |||
726 | 9319 | static int ff_vfscanf(FFFILE *f, const char *fmt, va_list ap) | |
727 | { | ||
728 | int width; | ||
729 | int size; | ||
730 | int base; | ||
731 | const unsigned char *p; | ||
732 | int c, t; | ||
733 | char *s; | ||
734 | 9319 | void *dest=NULL; | |
735 | int invert; | ||
736 | 9319 | int matches=0; | |
737 | unsigned long long x; | ||
738 | double y; | ||
739 | 9319 | ptrdiff_t pos = 0; | |
740 | unsigned char scanset[257]; | ||
741 | size_t i; | ||
742 | |||
743 |
2/2✓ Branch 0 taken 38462 times.
✓ Branch 1 taken 9114 times.
|
47576 | for (p=(const unsigned char *)fmt; *p; p++) { |
744 | |||
745 |
2/2✓ Branch 0 taken 372 times.
✓ Branch 1 taken 38090 times.
|
38462 | if (av_isspace(*p)) { |
746 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 372 times.
|
372 | while (av_isspace(p[1])) p++; |
747 | 372 | shlim(f, 0); | |
748 |
4/4✓ Branch 0 taken 656 times.
✓ Branch 1 taken 7 times.
✓ Branch 3 taken 291 times.
✓ Branch 4 taken 372 times.
|
663 | while (av_isspace(shgetc(f))); |
749 |
2/2✓ Branch 0 taken 365 times.
✓ Branch 1 taken 7 times.
|
372 | shunget(f); |
750 | 372 | pos += shcnt(f); | |
751 | 372 | continue; | |
752 | } | ||
753 |
3/4✓ Branch 0 taken 36819 times.
✓ Branch 1 taken 1271 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 36819 times.
|
38090 | if (*p != '%' || p[1] == '%') { |
754 | 1271 | shlim(f, 0); | |
755 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1271 times.
|
1271 | if (*p == '%') { |
756 | ✗ | p++; | |
757 | ✗ | while (av_isspace((c=shgetc(f)))); | |
758 | } else { | ||
759 |
2/2✓ Branch 0 taken 1234 times.
✓ Branch 1 taken 37 times.
|
1271 | c = shgetc(f); |
760 | } | ||
761 |
2/2✓ Branch 0 taken 125 times.
✓ Branch 1 taken 1146 times.
|
1271 | if (c!=*p) { |
762 |
2/2✓ Branch 0 taken 88 times.
✓ Branch 1 taken 37 times.
|
125 | shunget(f); |
763 |
2/2✓ Branch 0 taken 37 times.
✓ Branch 1 taken 88 times.
|
125 | if (c<0) goto input_fail; |
764 | 88 | goto match_fail; | |
765 | } | ||
766 | 1146 | pos += shcnt(f); | |
767 | 1146 | continue; | |
768 | } | ||
769 | |||
770 | 36819 | p++; | |
771 |
2/2✓ Branch 0 taken 360 times.
✓ Branch 1 taken 36459 times.
|
36819 | if (*p=='*') { |
772 | 360 | dest = 0; p++; | |
773 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 36459 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
36459 | } else if (av_isdigit(*p) && p[1]=='$') { |
774 | ✗ | dest = arg_n(ap, *p-'0'); p+=2; | |
775 | } else { | ||
776 | 36459 | dest = va_arg(ap, void *); | |
777 | } | ||
778 | |||
779 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36819 times.
|
36819 | for (width=0; av_isdigit(*p); p++) { |
780 | ✗ | width = 10*width + *p - '0'; | |
781 | } | ||
782 | |||
783 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36819 times.
|
36819 | if (*p=='m') { |
784 | ✗ | s = 0; | |
785 | ✗ | p++; | |
786 | } | ||
787 | |||
788 | 36819 | size = SIZE_def; | |
789 |
2/7✗ Branch 0 not taken.
✓ Branch 1 taken 297 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 36522 times.
✗ Branch 6 not taken.
|
36819 | switch (*p++) { |
790 | ✗ | case 'h': | |
791 | ✗ | if (*p == 'h') p++, size = SIZE_hh; | |
792 | ✗ | else size = SIZE_h; | |
793 | ✗ | break; | |
794 | 297 | case 'l': | |
795 |
2/2✓ Branch 0 taken 70 times.
✓ Branch 1 taken 227 times.
|
297 | if (*p == 'l') p++, size = SIZE_ll; |
796 | 227 | else size = SIZE_l; | |
797 | 297 | break; | |
798 | ✗ | case 'j': | |
799 | ✗ | size = SIZE_ll; | |
800 | ✗ | break; | |
801 | ✗ | case 'z': | |
802 | case 't': | ||
803 | ✗ | size = SIZE_l; | |
804 | ✗ | break; | |
805 | ✗ | case 'L': | |
806 | ✗ | size = SIZE_L; | |
807 | ✗ | break; | |
808 | 36522 | 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 '[': | ||
812 | case 'S': case 'C': | ||
813 | case 'p': case 'n': | ||
814 | 36522 | p--; | |
815 | 36522 | break; | |
816 | ✗ | default: | |
817 | ✗ | goto fmt_fail; | |
818 | } | ||
819 | |||
820 | 36819 | t = *p; | |
821 | |||
822 | /* C or S */ | ||
823 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36819 times.
|
36819 | if ((t&0x2f) == 3) { |
824 | ✗ | t |= 32; | |
825 | ✗ | size = SIZE_l; | |
826 | } | ||
827 | |||
828 |
4/4✓ Branch 0 taken 34177 times.
✓ Branch 1 taken 392 times.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 2199 times.
|
36819 | switch (t) { |
829 | 34177 | case 'c': | |
830 |
1/2✓ Branch 0 taken 34177 times.
✗ Branch 1 not taken.
|
34177 | if (width < 1) width = 1; |
831 | case '[': | ||
832 | 34569 | break; | |
833 | 51 | case 'n': | |
834 | 51 | store_int(dest, size, pos); | |
835 | /* do not increment match count, etc! */ | ||
836 | 51 | continue; | |
837 | 2199 | default: | |
838 | 2199 | shlim(f, 0); | |
839 |
4/4✓ Branch 0 taken 1607 times.
✓ Branch 1 taken 775 times.
✓ Branch 3 taken 183 times.
✓ Branch 4 taken 2199 times.
|
2382 | while (av_isspace(shgetc(f))); |
840 |
2/2✓ Branch 0 taken 2194 times.
✓ Branch 1 taken 5 times.
|
2199 | shunget(f); |
841 | 2199 | pos += shcnt(f); | |
842 | } | ||
843 | |||
844 | 36768 | shlim(f, width); | |
845 |
4/4✓ Branch 0 taken 28218 times.
✓ Branch 1 taken 8550 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 36762 times.
|
36768 | if (shgetc(f) < 0) goto input_fail; |
846 |
1/2✓ Branch 0 taken 36762 times.
✗ Branch 1 not taken.
|
36762 | shunget(f); |
847 | |||
848 |
3/7✓ Branch 0 taken 34568 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2133 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 61 times.
✗ Branch 6 not taken.
|
36762 | switch (t) { |
849 | 34568 | case 's': | |
850 | case 'c': | ||
851 | case '[': | ||
852 |
3/4✓ Branch 0 taken 392 times.
✓ Branch 1 taken 34176 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 392 times.
|
34568 | if (t == 'c' || t == 's') { |
853 | 34176 | memset(scanset, -1, sizeof scanset); | |
854 | 34176 | scanset[0] = 0; | |
855 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34176 times.
|
34176 | if (t == 's') { |
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; | |
862 | } | ||
863 | } else { | ||
864 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 360 times.
|
392 | if (*++p == '^') p++, invert = 1; |
865 | 360 | else invert = 0; | |
866 | 392 | memset(scanset, invert, sizeof scanset); | |
867 | 392 | scanset[0] = 0; | |
868 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 392 times.
|
392 | if (*p == '-') p++, scanset[1+'-'] = 1-invert; |
869 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 392 times.
|
392 | else if (*p == ']') p++, scanset[1+']'] = 1-invert; |
870 |
2/2✓ Branch 0 taken 752 times.
✓ Branch 1 taken 392 times.
|
1144 | for (; *p != ']'; p++) { |
871 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 752 times.
|
752 | if (!*p) goto fmt_fail; |
872 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 752 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
752 | if (*p=='-' && p[1] && p[1] != ']') |
873 | ✗ | for (c=p++[-1]; c<*p; c++) | |
874 | ✗ | scanset[1+c] = 1-invert; | |
875 | 752 | scanset[1+*p] = 1-invert; | |
876 | } | ||
877 | } | ||
878 | 34568 | s = 0; | |
879 | 34568 | i = 0; | |
880 |
2/2✓ Branch 0 taken 34208 times.
✓ Branch 1 taken 360 times.
|
34568 | if ((s = dest)) { |
881 |
4/4✓ Branch 0 taken 34521 times.
✓ Branch 1 taken 34177 times.
✓ Branch 3 taken 34490 times.
✓ Branch 4 taken 34208 times.
|
68698 | while (scanset[(c=shgetc(f))+1]) |
882 | 34490 | s[i++] = c; | |
883 | } else { | ||
884 |
3/4✓ Branch 0 taken 720 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 360 times.
✓ Branch 4 taken 360 times.
|
720 | while (scanset[(c=shgetc(f))+1]); |
885 | } | ||
886 |
2/2✓ Branch 0 taken 391 times.
✓ Branch 1 taken 34177 times.
|
34568 | shunget(f); |
887 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 34567 times.
|
34568 | if (!shcnt(f)) goto match_fail; |
888 |
3/4✓ Branch 0 taken 34176 times.
✓ Branch 1 taken 391 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 34176 times.
|
34567 | if (t == 'c' && shcnt(f) != width) goto match_fail; |
889 |
2/2✓ Branch 0 taken 391 times.
✓ Branch 1 taken 34176 times.
|
34567 | if (t != 'c') { |
890 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 360 times.
|
391 | if (s) s[i] = 0; |
891 | } | ||
892 | 34567 | break; | |
893 | ✗ | case 'p': | |
894 | case 'X': | ||
895 | case 'x': | ||
896 | ✗ | base = 16; | |
897 | ✗ | goto int_common; | |
898 | ✗ | case 'o': | |
899 | ✗ | base = 8; | |
900 | ✗ | goto int_common; | |
901 | 2133 | case 'd': | |
902 | case 'u': | ||
903 | 2133 | base = 10; | |
904 | 2133 | goto int_common; | |
905 | ✗ | case 'i': | |
906 | ✗ | base = 0; | |
907 | 2133 | int_common: | |
908 | 2133 | x = ffintscan(f, base, 0, ULLONG_MAX); | |
909 |
2/2✓ Branch 0 taken 73 times.
✓ Branch 1 taken 2060 times.
|
2133 | if (!shcnt(f)) |
910 | 73 | goto match_fail; | |
911 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 2060 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
2060 | if (t=='p' && dest) |
912 | ✗ | *(void **)dest = (void *)(uintptr_t)x; | |
913 | else | ||
914 | 2060 | store_int(dest, size, x); | |
915 | 2060 | break; | |
916 | 61 | case 'a': case 'A': | |
917 | case 'e': case 'E': | ||
918 | case 'f': case 'F': | ||
919 | case 'g': case 'G': | ||
920 | 61 | y = fffloatscan(f, size, 0); | |
921 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
|
61 | if (!shcnt(f)) |
922 | ✗ | goto match_fail; | |
923 |
1/2✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
|
61 | if (dest) { |
924 |
1/4✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
61 | switch (size) { |
925 | 61 | case SIZE_def: | |
926 | 61 | *(float *)dest = y; | |
927 | 61 | break; | |
928 | ✗ | case SIZE_l: | |
929 | ✗ | *(double *)dest = y; | |
930 | ✗ | break; | |
931 | ✗ | case SIZE_L: | |
932 | ✗ | *(double *)dest = y; | |
933 | ✗ | break; | |
934 | } | ||
935 | } | ||
936 | 61 | break; | |
937 | } | ||
938 | |||
939 | 36688 | pos += shcnt(f); | |
940 |
2/2✓ Branch 0 taken 36328 times.
✓ Branch 1 taken 360 times.
|
36688 | if (dest) matches++; |
941 | } | ||
942 | if (0) { | ||
943 | ✗ | fmt_fail: | |
944 | 43 | input_fail: | |
945 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 5 times.
|
43 | if (!matches) matches--; |
946 | } | ||
947 | 9152 | match_fail: | |
948 | 9319 | return matches; | |
949 | } | ||
950 | |||
951 | 9319 | static int ff_vsscanf(const char *s, const char *fmt, va_list ap) | |
952 | { | ||
953 | 9319 | FFFILE f = { | |
954 | .buf = (void *)s, .cookie = (void *)s, | ||
955 | .read = ffstring_read, | ||
956 | }; | ||
957 | |||
958 | 9319 | return ff_vfscanf(&f, fmt, ap); | |
959 | } | ||
960 | |||
961 | 9319 | int av_sscanf(const char *string, const char *format, ...) | |
962 | { | ||
963 | int ret; | ||
964 | va_list ap; | ||
965 | 9319 | va_start(ap, format); | |
966 | 9319 | ret = ff_vsscanf(string, format, ap); | |
967 | 9319 | va_end(ap); | |
968 | 9319 | return ret; | |
969 | } | ||
970 |