GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* |
||
2 |
Teem: Tools to process and visualize scientific data and images . |
||
3 |
Copyright (C) 2013, 2012, 2011, 2010, 2009 University of Chicago |
||
4 |
Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann |
||
5 |
Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah |
||
6 |
|||
7 |
This library is free software; you can redistribute it and/or |
||
8 |
modify it under the terms of the GNU Lesser General Public License |
||
9 |
(LGPL) as published by the Free Software Foundation; either |
||
10 |
version 2.1 of the License, or (at your option) any later version. |
||
11 |
The terms of redistributing and/or modifying this software also |
||
12 |
include exceptions to the LGPL that facilitate static linking. |
||
13 |
|||
14 |
This library is distributed in the hope that it will be useful, |
||
15 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
16 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
17 |
Lesser General Public License for more details. |
||
18 |
|||
19 |
You should have received a copy of the GNU Lesser General Public License |
||
20 |
along with this library; if not, write to Free Software Foundation, Inc., |
||
21 |
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||
22 |
*/ |
||
23 |
|||
24 |
#include "air.h" |
||
25 |
|||
26 |
static const char * |
||
27 |
_airBoolStr[] = { |
||
28 |
"(unknown bool)", |
||
29 |
"false", |
||
30 |
"true" |
||
31 |
}; |
||
32 |
|||
33 |
static const char * |
||
34 |
_airBoolDesc[] = { |
||
35 |
"unknown boolean", |
||
36 |
"false", |
||
37 |
"true" |
||
38 |
}; |
||
39 |
|||
40 |
static const int |
||
41 |
_airBoolVal[] = { |
||
42 |
-1, |
||
43 |
AIR_FALSE, |
||
44 |
AIR_TRUE |
||
45 |
}; |
||
46 |
|||
47 |
static const char * |
||
48 |
_airBoolStrEqv[] = { |
||
49 |
"0", "no", "n", "false", "f", "off", "nope", |
||
50 |
"1", "yes", "y", "true", "t", "on", "yea", |
||
51 |
"" |
||
52 |
}; |
||
53 |
|||
54 |
static const int |
||
55 |
_airBoolValEqv[] = { |
||
56 |
AIR_FALSE, AIR_FALSE, AIR_FALSE, AIR_FALSE, AIR_FALSE, AIR_FALSE, AIR_FALSE, |
||
57 |
AIR_TRUE, AIR_TRUE, AIR_TRUE, AIR_TRUE, AIR_TRUE, AIR_TRUE, AIR_TRUE |
||
58 |
}; |
||
59 |
|||
60 |
static const airEnum |
||
61 |
_airBool = { |
||
62 |
"boolean", |
||
63 |
2, |
||
64 |
_airBoolStr, |
||
65 |
_airBoolVal, |
||
66 |
_airBoolDesc, |
||
67 |
_airBoolStrEqv, |
||
68 |
_airBoolValEqv, |
||
69 |
AIR_FALSE |
||
70 |
}; |
||
71 |
|||
72 |
const airEnum *const |
||
73 |
airBool = &_airBool; |
||
74 |
|||
75 |
double |
||
76 |
airAtod(const char *str) { |
||
77 |
520 |
double val = 0.0; |
|
78 |
|||
79 |
260 |
airSingleSscanf(str, "%lf", &val); |
|
80 |
520 |
return val; |
|
81 |
260 |
} |
|
82 |
|||
83 |
int |
||
84 |
airSingleSscanf(const char *str, const char *fmt, void *ptr) { |
||
85 |
char *tmp; |
||
86 |
double val; |
||
87 |
int ret; |
||
88 |
|||
89 |
✓✗✓✗ ✓✓ |
7049 |
if (!strcmp(fmt, "%e") || !strcmp(fmt, "%f") || !strcmp(fmt, "%g") |
90 |
✓✗✓✗ ✓✓ |
5516 |
|| !strcmp(fmt, "%le") || !strcmp(fmt, "%lf") || !strcmp(fmt, "%lg")) { |
91 |
1282 |
tmp = airStrdup(str); |
|
92 |
✗✓ | 1282 |
if (!tmp) { |
93 |
return 0; |
||
94 |
} |
||
95 |
1282 |
airToLower(tmp); |
|
96 |
✓✓ | 1282 |
if (strstr(tmp, "nan")) { |
97 |
66 |
val = AIR_NAN; |
|
98 |
66 |
} |
|
99 |
/* ---- BEGIN non-NrrdIO */ |
||
100 |
✗✓ | 1216 |
else if (strstr(tmp, "-pi")) { |
101 |
val = -AIR_PI; |
||
102 |
} |
||
103 |
✗✓ | 1216 |
else if (strstr(tmp, "pi")) { |
104 |
val = AIR_PI; |
||
105 |
} |
||
106 |
/* ---- END non-NrrdIO */ |
||
107 |
✗✓ | 1216 |
else if (strstr(tmp, "-inf")) { |
108 |
val = AIR_NEG_INF; |
||
109 |
} |
||
110 |
✗✓ | 1216 |
else if (strstr(tmp, "inf")) { |
111 |
val = AIR_POS_INF; |
||
112 |
} |
||
113 |
else { |
||
114 |
/* nothing special matched; pass it off to sscanf() */ |
||
115 |
/* (save setlocale here) */ |
||
116 |
1216 |
ret = sscanf(str, fmt, ptr); |
|
117 |
/* (return setlocale here) */ |
||
118 |
1216 |
free(tmp); |
|
119 |
1216 |
return ret; |
|
120 |
} |
||
121 |
/* else we matched "nan", "-inf", or "inf", and set val accordingly */ |
||
122 |
✓✗ | 66 |
if (!strncmp(fmt, "%l", 2)) { |
123 |
/* we were given a double pointer */ |
||
124 |
66 |
*((double *)(ptr)) = val; |
|
125 |
66 |
} |
|
126 |
else { |
||
127 |
/* we were given a float pointer */ |
||
128 |
*((float *)(ptr)) = AIR_CAST(float, val); |
||
129 |
} |
||
130 |
66 |
free(tmp); |
|
131 |
66 |
return 1; |
|
132 |
✓✓ | 251 |
} else if (!strcmp(fmt, "%z")) { |
133 |
/* its a size_t */ |
||
134 |
size_t tsz = 0; /* tmp size_t */ |
||
135 |
const char *chh = str; /* char here */ |
||
136 |
✓✗✓✓ |
730 |
while (chh) { |
137 |
int dig; |
||
138 |
562 |
dig = AIR_CAST(int, *chh - '0'); |
|
139 |
✓✓ | 562 |
if (AIR_IN_CL(0, dig, 9)) { |
140 |
394 |
tsz = 10*tsz + AIR_CAST(size_t, dig); |
|
141 |
} else { |
||
142 |
168 |
break; |
|
143 |
} |
||
144 |
394 |
chh++; |
|
145 |
394 |
} |
|
146 |
168 |
*((size_t *)(ptr)) = tsz; |
|
147 |
return 1; |
||
148 |
} else { |
||
149 |
/* not a float, double, or size_t, let sscanf handle it */ |
||
150 |
83 |
return sscanf(str, fmt, ptr); |
|
151 |
} |
||
152 |
1533 |
} |
|
153 |
|||
154 |
#define _PARSE_STR_ARGS(type) type *out, const char *_s, \ |
||
155 |
const char *ct, unsigned int n, ... |
||
156 |
#define _PARSE_STR_BODY(format) \ |
||
157 |
unsigned int i; \ |
||
158 |
char *tmp, *s, *last; \ |
||
159 |
\ |
||
160 |
/* if we got NULL, there's nothing to do */ \ |
||
161 |
if (!(out && _s && ct)) \ |
||
162 |
return 0; \ |
||
163 |
\ |
||
164 |
/* copy the input so that we don't change it */ \ |
||
165 |
s = airStrdup(_s); \ |
||
166 |
\ |
||
167 |
/* keep calling airStrtok() until we have everything */ \ |
||
168 |
for (i=0; i<n; i++) { \ |
||
169 |
tmp = airStrtok(i ? NULL : s, ct, &last); \ |
||
170 |
if (!tmp) { \ |
||
171 |
free(s); \ |
||
172 |
return i; \ |
||
173 |
} \ |
||
174 |
if (1 != airSingleSscanf(tmp, format, out+i)) { \ |
||
175 |
free(s); \ |
||
176 |
return i; \ |
||
177 |
} \ |
||
178 |
} \ |
||
179 |
free(s); \ |
||
180 |
return n; \ |
||
181 |
|||
182 |
/* |
||
183 |
******* airParse*() |
||
184 |
** |
||
185 |
** parse ints, floats, doubles, or single characters, from some |
||
186 |
** given string "s"; try to parse "n" of them, as delimited by |
||
187 |
** characters in "ct", and put the results in "out". |
||
188 |
** |
||
189 |
** Returns the number of things succesfully parsed- should be n; |
||
190 |
** there's been an error if return is < n. |
||
191 |
** |
||
192 |
** The embarrassing reason for the var-args ("...") is that I want the |
||
193 |
** type signature of all these functions to be the same, and I have a function |
||
194 |
** for parsing airEnums, in case the airEnum must be supplied as a final |
||
195 |
** argument. |
||
196 |
** |
||
197 |
** This uses air's thread-safe strtok() replacement: airStrtok() |
||
198 |
*/ |
||
199 |
unsigned int |
||
200 |
✗✓✓✓ ✗✓✗✓ |
224 |
airParseStrI(_PARSE_STR_ARGS(int)) { _PARSE_STR_BODY("%d") } |
201 |
|||
202 |
unsigned int |
||
203 |
✗✓✓✓ ✗✓✗✓ |
200 |
airParseStrUI(_PARSE_STR_ARGS(unsigned int)) { _PARSE_STR_BODY("%u") } |
204 |
|||
205 |
unsigned int |
||
206 |
airParseStrLI(_PARSE_STR_ARGS(long int)) { _PARSE_STR_BODY("%ld") } |
||
207 |
|||
208 |
unsigned int |
||
209 |
airParseStrULI(_PARSE_STR_ARGS(unsigned long int)) { _PARSE_STR_BODY("%lu") } |
||
210 |
|||
211 |
unsigned int |
||
212 |
✗✓✓✓ ✓✓✗✓ |
1043 |
airParseStrZ(_PARSE_STR_ARGS(size_t)) { _PARSE_STR_BODY("%z") } |
213 |
|||
214 |
unsigned int |
||
215 |
airParseStrF(_PARSE_STR_ARGS(float)) { _PARSE_STR_BODY("%f") } |
||
216 |
|||
217 |
unsigned int |
||
218 |
✗✓✓✓ ✓✓✗✓ |
2416 |
airParseStrD(_PARSE_STR_ARGS(double)) { _PARSE_STR_BODY("%lf") } |
219 |
|||
220 |
unsigned int |
||
221 |
airParseStrB(int *out, const char *_s, const char *ct, unsigned int n, ...) { |
||
222 |
unsigned int i; |
||
223 |
char *tmp, *s, *last; |
||
224 |
|||
225 |
/* if we got NULL, there's nothing to do */ |
||
226 |
if (!(out && _s && ct)) |
||
227 |
return 0; |
||
228 |
|||
229 |
/* copy the input so that we don't change it */ |
||
230 |
s = airStrdup(_s); |
||
231 |
|||
232 |
/* keep calling airStrtok() until we have everything */ |
||
233 |
for (i=0; i<n; i++) { |
||
234 |
tmp = airStrtok(i ? NULL : s, ct, &last); |
||
235 |
if (!tmp) { |
||
236 |
free(s); |
||
237 |
return i; |
||
238 |
} |
||
239 |
out[i] = airEnumVal(airBool, tmp); |
||
240 |
if (airEnumUnknown(airBool) == out[i]) { |
||
241 |
free(s); |
||
242 |
return i; |
||
243 |
} |
||
244 |
} |
||
245 |
free(s); |
||
246 |
return n; |
||
247 |
} |
||
248 |
|||
249 |
unsigned int |
||
250 |
airParseStrC(char *out, const char *_s, const char *ct, unsigned int n, ...) { |
||
251 |
unsigned int i; |
||
252 |
char *tmp, *s, *last; |
||
253 |
|||
254 |
/* if we got NULL, there's nothing to do */ |
||
255 |
if (!(out && _s && ct)) |
||
256 |
return 0; |
||
257 |
|||
258 |
/* copy the input so that we don't change it */ |
||
259 |
s = airStrdup(_s); |
||
260 |
|||
261 |
/* keep calling airStrtok() until we have everything */ |
||
262 |
for (i=0; i<n; i++) { |
||
263 |
tmp = airStrtok(i ? NULL : s, ct, &last); |
||
264 |
if (!tmp) { |
||
265 |
free(s); |
||
266 |
return i; |
||
267 |
} |
||
268 |
out[i] = tmp[0]; |
||
269 |
} |
||
270 |
free(s); |
||
271 |
return n; |
||
272 |
} |
||
273 |
|||
274 |
unsigned int |
||
275 |
airParseStrS(char **out, const char *_s, const char *ct, unsigned int n, ...) { |
||
276 |
unsigned int i; |
||
277 |
int greedy; |
||
278 |
1004 |
char *tmp, *s, *last; |
|
279 |
airArray *mop; |
||
280 |
502 |
va_list ap; |
|
281 |
|||
282 |
/* grab "greedy" every time, prior to error checking */ |
||
283 |
502 |
va_start(ap, n); |
|
284 |
✓✗ | 1506 |
greedy = va_arg(ap, int); |
285 |
502 |
va_end(ap); |
|
286 |
|||
287 |
/* if we got NULL, there's nothing to do */ |
||
288 |
✗✓ | 502 |
if (!(out && _s && ct)) |
289 |
return 0; |
||
290 |
|||
291 |
502 |
mop = airMopNew(); |
|
292 |
/* copy the input so that we don't change it */ |
||
293 |
502 |
s = airStrdup(_s); |
|
294 |
502 |
airMopMem(mop, &s, airMopAlways); |
|
295 |
|||
296 |
/* keep calling airStrtok() until we have everything */ |
||
297 |
✓✓ | 4260 |
for (i=0; i<n; i++) { |
298 |
/* if n == 1, then with greediness, the whole string is used, |
||
299 |
and without greediness, we use airStrtok() to get only |
||
300 |
the first part of it */ |
||
301 |
✓✓ | 1788 |
if (n > 1 || !greedy) { |
302 |
1772 |
tmp = airStrtok(i ? NULL : s, ct, &last); |
|
303 |
1772 |
} |
|
304 |
else { |
||
305 |
16 |
tmp = s; |
|
306 |
} |
||
307 |
✓✓ | 1788 |
if (!tmp) { |
308 |
160 |
airMopError(mop); |
|
309 |
160 |
return i; |
|
310 |
} |
||
311 |
1628 |
out[i] = airStrdup(tmp); |
|
312 |
✗✓ | 1628 |
if (!out[i]) { |
313 |
airMopError(mop); |
||
314 |
return i; |
||
315 |
} |
||
316 |
1628 |
airMopMem(mop, out+i, airMopOnError); |
|
317 |
} |
||
318 |
342 |
airMopOkay(mop); |
|
319 |
342 |
return n; |
|
320 |
502 |
} |
|
321 |
|||
322 |
unsigned int |
||
323 |
airParseStrE(int *out, const char *_s, const char *ct, unsigned int n, ...) { |
||
324 |
unsigned int i; |
||
325 |
char *tmp, *s, *last; |
||
326 |
airArray *mop; |
||
327 |
va_list ap; |
||
328 |
airEnum *enm; |
||
329 |
|||
330 |
/* grab the enum every time, prior to error checking */ |
||
331 |
va_start(ap, n); |
||
332 |
enm = va_arg(ap, airEnum *); |
||
333 |
va_end(ap); |
||
334 |
|||
335 |
/* if we got NULL, there's nothing to do */ |
||
336 |
if (!(out && _s && ct)) { |
||
337 |
return 0; |
||
338 |
} |
||
339 |
|||
340 |
mop = airMopNew(); |
||
341 |
/* copy the input so that we don't change it */ |
||
342 |
s = airStrdup(_s); |
||
343 |
airMopMem(mop, &s, airMopAlways); |
||
344 |
|||
345 |
if (1 == n) { |
||
346 |
/* Because it should be permissible to have spaces in what is |
||
347 |
intended to be only a single string from an airEnum, we treat |
||
348 |
1==n differently, and do NOT use airStrtok to tokenize the |
||
349 |
input string s into spaces. We check the whole s string */ |
||
350 |
out[0] = airEnumVal(enm, s); |
||
351 |
if (airEnumUnknown(enm) == out[0]) { |
||
352 |
airMopError(mop); |
||
353 |
return 0; |
||
354 |
} |
||
355 |
} else { |
||
356 |
/* keep calling airStrtok() until we have everything */ |
||
357 |
for (i=0; i<n; i++) { |
||
358 |
tmp = airStrtok(i ? NULL : s, ct, &last); |
||
359 |
if (!tmp) { |
||
360 |
airMopError(mop); |
||
361 |
return i; |
||
362 |
} |
||
363 |
out[i] = airEnumVal(enm, tmp); |
||
364 |
if (airEnumUnknown(enm) == out[i] |
||
365 |
/* getting the unknown value is not a parse failure if the |
||
366 |
string was actually the string for the unknown value! */ |
||
367 |
&& strcmp(tmp, enm->str[0])) { |
||
368 |
airMopError(mop); |
||
369 |
return i; |
||
370 |
} |
||
371 |
} |
||
372 |
} |
||
373 |
airMopOkay(mop); |
||
374 |
return n; |
||
375 |
} |
||
376 |
|||
377 |
unsigned int |
||
378 |
(*airParseStr[AIR_TYPE_MAX+1])(void *, const char *, |
||
379 |
const char *, unsigned int, ...) = { |
||
380 |
NULL, |
||
381 |
(unsigned int (*)(void *, const char *, const char *, |
||
382 |
unsigned int, ...))airParseStrB, |
||
383 |
(unsigned int (*)(void *, const char *, const char *, |
||
384 |
unsigned int, ...))airParseStrI, |
||
385 |
(unsigned int (*)(void *, const char *, const char *, |
||
386 |
unsigned int, ...))airParseStrUI, |
||
387 |
(unsigned int (*)(void *, const char *, const char *, |
||
388 |
unsigned int, ...))airParseStrLI, |
||
389 |
(unsigned int (*)(void *, const char *, const char *, |
||
390 |
unsigned int, ...))airParseStrULI, |
||
391 |
(unsigned int (*)(void *, const char *, const char *, |
||
392 |
unsigned int, ...))airParseStrZ, |
||
393 |
(unsigned int (*)(void *, const char *, const char *, |
||
394 |
unsigned int, ...))airParseStrF, |
||
395 |
(unsigned int (*)(void *, const char *, const char *, |
||
396 |
unsigned int, ...))airParseStrD, |
||
397 |
(unsigned int (*)(void *, const char *, const char *, |
||
398 |
unsigned int, ...))airParseStrC, |
||
399 |
(unsigned int (*)(void *, const char *, const char *, |
||
400 |
unsigned int, ...))airParseStrS, |
||
401 |
(unsigned int (*)(void *, const char *, const char *, |
||
402 |
unsigned int, ...))airParseStrE, |
||
403 |
NULL /* no standard way of parsing type "other" */ |
||
404 |
}; |
||
405 |
Generated by: GCOVR (Version 3.3) |