int _nrrdEncodingAscii_read(FILE *file, void *_data, size_t elNum, Nrrd *nrrd, NrrdIoState *nio) { static const char me[]="_nrrdEncodingAscii_read"; char numbStr[AIR_STRLEN_HUGE]; /* HEY: fix this */ char *nstr; size_t I; char *data; int tmp; AIR_UNUSED(nio); if (nrrdTypeBlock == nrrd->type) { biffAddf(NRRD, "%s: can't read nrrd type %s from %s", me, airEnumStr(nrrdType, nrrdTypeBlock), nrrdEncodingAscii->name); return 1; } data = (char*)_data; I = 0; while (I < elNum) { if (1 != fscanf(file, "%s", numbStr)) { biffAddf(NRRD, "%s: couldn't parse element " _AIR_SIZE_T_CNV " of " _AIR_SIZE_T_CNV, me, I+1, elNum); return 1; } if (!strcmp(",", numbStr)) { /* its an isolated comma, not a value, pass over this */ continue; } /* get past any commas prefixing a number (without space) */ nstr = numbStr + strspn(numbStr, ","); if (nrrd->type >= nrrdTypeInt) { /* sscanf supports putting value directly into this type */ if (1 != airSingleSscanf(nstr, nrrdTypePrintfStr[nrrd->type], (void*)(data + I*nrrdElementSize(nrrd)))) { biffAddf(NRRD, "%s: couln't parse %s " _AIR_SIZE_T_CNV " of " _AIR_SIZE_T_CNV " (\"%s\")", me, airEnumStr(nrrdType, nrrd->type), I+1, elNum, nstr); return 1; } } else { /* sscanf value into an int first */ if (1 != airSingleSscanf(nstr, "%d", &tmp)) { biffAddf(NRRD, "%s: couln't parse element " _AIR_SIZE_T_CNV " of " _AIR_SIZE_T_CNV " (\"%s\")", me, I+1, elNum, nstr); return 1; } nrrdIInsert[nrrd->type](data, I, tmp); } I++; } return 0; }
double airAtod(const char *str) { double val = 0.0; airSingleSscanf(str, "%lf", &val); return val; }
int _nrrdEncodingAscii_read(FILE *file, void *_data, size_t elNum, Nrrd *nrrd, NrrdIoState *nio) { char me[]="_nrrdEncodingAscii_read", err[BIFF_STRLEN], numbStr[AIR_STRLEN_HUGE]; /* HEY: fix this */ size_t I; char *data; int tmp; AIR_UNUSED(nio); if (nrrdTypeBlock == nrrd->type) { sprintf(err, "%s: can't read nrrd type %s from %s", me, airEnumStr(nrrdType, nrrdTypeBlock), nrrdEncodingAscii->name); biffAdd(NRRD, err); return 1; } data = (char*)_data; for (I=0; I<elNum; I++) { if (1 != fscanf(file, "%s", numbStr)) { sprintf(err, "%s: couldn't parse element " _AIR_SIZE_T_CNV " of " _AIR_SIZE_T_CNV, me, I+1, elNum); biffAdd(NRRD, err); return 1; } if (nrrd->type >= nrrdTypeInt) { /* sscanf supports putting value directly into this type */ if (1 != airSingleSscanf(numbStr, nrrdTypePrintfStr[nrrd->type], (void*)(data + I*nrrdElementSize(nrrd)))) { sprintf(err, "%s: couln't parse %s " _AIR_SIZE_T_CNV " of " _AIR_SIZE_T_CNV " (\"%s\")", me, airEnumStr(nrrdType, nrrd->type), I+1, elNum, numbStr); biffAdd(NRRD, err); return 1; } } else { /* sscanf value into an int first */ if (1 != airSingleSscanf(numbStr, "%d", &tmp)) { sprintf(err, "%s: couln't parse element " _AIR_SIZE_T_CNV " of " _AIR_SIZE_T_CNV " (\"%s\")", me, I+1, elNum, numbStr); biffAdd(NRRD, err); return 1; } nrrdIInsert[nrrd->type](data, I, tmp); } } return 0; }
int main(int argc, char *argv[]) { char *fS, buff[128]; float f; double d, sd; int ret; me = argv[0]; if (2 != argc) { fprintf(stderr, "usage: %s <double>\n", me); exit(1); } fS = argv[1]; ret = sscanf(fS, "%lf", &sd); if (!ret) { printf("%s: sscanf(%s, \"%%lf\") failed\n", me, fS); printf("\n"); } if (1 != airSingleSscanf(fS, "%lf", &d)) { fprintf(stderr, "%s: couldn't parse \"%s\" as double\n", me, fS); exit(1); } if (ret && (sd != d)) { printf("%s: sscanf result (%f) != airSingleSscanf (%f)!!!\n", me, sd, d); printf("\n"); } f = d; airSinglePrintf(NULL, buff, "%f", f); printf("%s: printf/airSinglePrintf as float:\n%f\n%s\n", me, f, buff); airSinglePrintf(NULL, buff, "%lf", d); printf("\n"); printf("%s: printf/airSinglePrintf as double:\n%f\n%s\n", me, d, buff); printf("\n"); printf("%s: airFPFprintf_d:\n", me); airFPFprintf_d(stderr, d); exit(0); }
int _nrrdHestIterParse(void *ptr, char *str, char err[AIR_STRLEN_HUGE]) { char me[]="_nrrdHestIterParse", *nerr; Nrrd *nrrd; NrrdIter **iterP; airArray *mop; double val; int ret; if (!(ptr && str)) { sprintf(err, "%s: got NULL pointer", me); return 1; } iterP = (NrrdIter **)ptr; mop = airMopNew(); *iterP = nrrdIterNew(); airMopAdd(mop, *iterP, (airMopper)nrrdIterNix, airMopOnError); /* the challenge here is determining if a given string represents a filename or a number. Obviously there are cases where it could be both, so we'll assume its a filename first. Because: there are different ways of writing the same number, such as "3" --> "+3", "3.1" --> "3.10", so someone accidently using the file when they mean to use the number has easy ways of changing the number representation, since these trivial transformations will probably not all result in valid filenames. Another problem is that one really wants a general robust test to see if a given string is a valid number representation AND NOTHING BUT THAT, and sscanf() is not that test. In any case, if there are to be improved smarts about this matter, they need to be implemented below and nowhere else. */ nrrd = nrrdNew(); ret = nrrdLoad(nrrd, str, NULL); if (!ret) { /* first attempt at nrrdLoad() was SUCCESSFUL */ nrrdIterSetOwnNrrd(*iterP, nrrd); } else { /* so it didn't load as a nrrd- if its because fopen() failed, then we'll try it as a number. If its for another reason, then we complain */ nrrdNuke(nrrd); if (2 != ret) { /* it failed because of something besides the fopen(), so complain */ nerr = biffGetDone(NRRD); airStrcpy(err, AIR_STRLEN_HUGE, nerr); airMopError(mop); return 1; } else { /* fopen() failed, so it probably wasn't meant to be a filename */ free(biffGetDone(NRRD)); ret = airSingleSscanf(str, "%lf", &val); if (_nrrdLooksLikeANumber(str) || (1 == ret && (!AIR_EXISTS(val) || AIR_ABS(AIR_PI - val) < 0.0001))) { /* either it patently looks like a number, or, it already parsed as a number and it is a special value */ if (1 == ret) { nrrdIterSetValue(*iterP, val); } else { /* oh, this is bad. */ fprintf(stderr, "%s: PANIC, is it a number or not?", me); exit(1); } } else { /* it doesn't look like a number, but the fopen failed, so we'll let it fail again and pass back the error messages */ if (nrrdLoad(nrrd = nrrdNew(), str, NULL)) { nerr = biffGetDone(NRRD); airStrcpy(err, AIR_STRLEN_HUGE, nerr); airMopError(mop); return 1; } else { /* what the hell? */ fprintf(stderr, "%s: PANIC, is it a nrrd or not?", me); exit(1); } } } } airMopAdd(mop, iterP, (airMopper)airSetNull, airMopOnError); airMopOkay(mop); return 0; }
static int _nrrdEncodingAscii_read(FILE *file, void *_data, size_t elNum, Nrrd *nrrd, NrrdIoState *nio) { static const char me[]="_nrrdEncodingAscii_read"; char numbStr[AIR_STRLEN_HUGE]; /* HEY: fix this */ char *nstr; size_t I; char *data; int tmp; AIR_UNUSED(nio); _fileSave = file; if (nrrdTypeBlock == nrrd->type) { biffAddf(NRRD, "%s: can't read nrrd type %s from %s", me, airEnumStr(nrrdType, nrrdTypeBlock), nrrdEncodingAscii->name); return 1; } data = (char*)_data; I = 0; while (I < elNum) { char stmp1[AIR_STRLEN_SMALL], stmp2[AIR_STRLEN_SMALL]; /* HEY: we can easily suffer here from a standard buffer overflow problem; this was a source of a mysterious unu crash: echo "0 0 0 0 1 0 0 0 0" \ | unu reshape -s 9 1 1 \ | unu pad -min 0 0 0 -max 8 8 8 \ | unu make -s 9 9 9 -t float -e ascii -ls 9 \ -spc LPS -orig "(0,0,0)" -dirs "(1,0,0) (0,1,0) (0,0,1)" This particular case is resolved by changing AIR_STRLEN_HUGE to AIR_STRLEN_HUGE*100, but the general problem remains. This motivated adding the memory corruption test */ if (1 != fscanf(file, "%s", numbStr)) { biffAddf(NRRD, "%s: couldn't parse element %s of %s", me, airSprintSize_t(stmp1, I+1), airSprintSize_t(stmp2, elNum)); return 1; } if (file != _fileSave) { fprintf(stderr, "%s: PANIC memory corruption detected\n", me); /* this may crash, hence the fprintf above to help debug */ biffAddf(NRRD, "%s: PANIC memory corruption detected", me); return 1; } if (!strcmp(",", numbStr)) { /* its an isolated comma, not a value, pass over this */ continue; } /* get past any commas prefixing a number (without space) */ nstr = numbStr + strspn(numbStr, ","); if (nrrd->type >= nrrdTypeInt) { /* sscanf supports putting value directly into this type */ if (1 != airSingleSscanf(nstr, nrrdTypePrintfStr[nrrd->type], (void*)(data + I*nrrdElementSize(nrrd)))) { biffAddf(NRRD, "%s: couldn't parse %s %s of %s (\"%s\")", me, airEnumStr(nrrdType, nrrd->type), airSprintSize_t(stmp1, I+1), airSprintSize_t(stmp2, elNum), nstr); return 1; } } else { /* sscanf value into an int first */ if (1 != airSingleSscanf(nstr, "%d", &tmp)) { biffAddf(NRRD, "%s: couldn't parse element %s of %s (\"%s\")", me, airSprintSize_t(stmp1, I+1), airSprintSize_t(stmp2, elNum), nstr); return 1; } nrrdIInsert[nrrd->type](data, I, tmp); } I++; } return 0; }