/* ******** nrrdCommentAdd() ** ** Adds a given string to the list of comments ** Leading spaces (' ') and comment chars ('#') are not included. ** ** This function does NOT use biff. */ int nrrdCommentAdd(Nrrd *nrrd, const char *_str) { char /* me[]="nrrdCommentAdd", err[512], */ *str; int i; if (!(nrrd && _str)) { /* sprintf(err, "%s: got NULL pointer", me); biffMaybeAdd(NRRD, err, useBiff); */ return 1; } _str += strspn(_str, " #"); if (!strlen(_str)) { /* we don't bother adding comments with no length */ return 0; } if (!strcmp(_str, _nrrdFormatURLLine0) || !strcmp(_str, _nrrdFormatURLLine1)) { /* sneaky hack: don't store the format URL comment lines */ return 0; } str = airStrdup(_str); if (!str) { /* sprintf(err, "%s: couldn't strdup given string", me); biffMaybeAdd(NRRD, err, useBiff); */ return 1; } /* clean out carraige returns that would screw up reader */ airOneLinify(str); i = airArrayLenIncr(nrrd->cmtArr, 1); if (!nrrd->cmtArr->data) { /* sprintf(err, "%s: couldn't lengthen comment array", me); biffMaybeAdd(NRRD, err, useBiff); */ return 1; } nrrd->cmt[i] = str; return 0; }
/* ** adds a given message to the given entry. The message is processed to ** convert all whitespace into ' ', and to eliminate whitespace at the ** end of the message. */ void biffMsgAdd(biffMsg *msg, const char *err) { static const char me[]="biffMsgAdd"; unsigned int idx; if (biffMsgNoop == msg) { return; } if (!( msg && err )) { fprintf(stderr, "%s: PANIC got NULL msg (%p) or err (%p)\n", me, AIR_VOIDP(msg), AIR_CVOIDP(err)); /* exit(1); */ } idx = airArrayLenIncr(msg->errArr, 1); if (!msg->err) { fprintf(stderr, "%s: PANIC: couldn't add message to %s\n", me, msg->key); /* exit(1); */ } if (!( msg->err[idx] = airOneLinify(airStrdup(err)) )) { fprintf(stderr, "%s: PANIC: couldn't alloc message to %s\n", me, msg->key); /* exit(1); */ } return; }
void hestGlossary(FILE *f, hestOpt *opt, hestParm *_parm) { int i, j, len, maxlen, numOpts; char buff[2*AIR_STRLEN_HUGE], tmpS[AIR_STRLEN_HUGE]; hestParm *parm; parm = !_parm ? hestParmNew() : _parm; if (_hestPanic(opt, NULL, parm)) { /* we can't continue; the opt array is botched */ parm = !_parm ? hestParmFree(parm) : NULL; return; } numOpts = _hestNumOpts(opt); maxlen = 0; if (numOpts) { fprintf(f, "\n"); } for (i=0; i<numOpts; i++) { strcpy(buff, ""); _hestSetBuff(buff, opt + i, parm, AIR_TRUE, AIR_FALSE); maxlen = AIR_MAX((int)strlen(buff), maxlen); } if (parm && parm->respFileEnable) { sprintf(buff, "%cfile ...", parm->respFileFlag); len = strlen(buff); for (j=len; j<maxlen; j++) { fprintf(f, " "); } fprintf(f, "%s = ", buff); strcpy(buff, "response file(s) containing command-line arguments"); _hestPrintStr(f, maxlen + 3, maxlen + 3, parm->columns, buff, AIR_FALSE); } for (i=0; i<numOpts; i++) { strcpy(buff, ""); _hestSetBuff(buff, opt + i, parm, AIR_TRUE, AIR_FALSE); airOneLinify(buff); len = strlen(buff); for (j=len; j<maxlen; j++) { fprintf(f, " "); } fprintf(f, "%s", buff); strcpy(buff, ""); #if 1 if (opt[i].flag && strchr(opt[i].flag, parm->multiFlagSep)) { /* there is a long-form flag as well as short */ _hestSetBuff(buff, opt + i, parm, AIR_FALSE, AIR_TRUE); strcat(buff, " = "); fprintf(f, " , "); } else { /* there is only a short-form flag */ fprintf(f, " = "); } #else fprintf(f, " = "); #endif if (opt[i].info) { strcat(buff, opt[i].info); } if ((opt[i].min || _hestMax(opt[i].max)) && (!( 2 == opt[i].kind && airTypeEnum == opt[i].type && parm->elideSingleEnumType )) && (!( 2 == opt[i].kind && airTypeOther == opt[i].type && parm->elideSingleOtherType )) ) { /* if there are newlines in the info, then we want to clarify the type by printing it on its own line */ if (opt[i].info && strchr(opt[i].info, '\n')) { strcat(buff, "\n "); } else { strcat(buff, " "); } strcat(buff, "("); if (opt[i].min == 0 && _hestMax(opt[i].max) == 1) { strcat(buff, "optional\t"); } else { if ((int)opt[i].min == _hestMax(opt[i].max) && _hestMax(opt[i].max) > 1) { /* HEY scrutinize casts */ sprintf(tmpS, "%d\t", _hestMax(opt[i].max)); strcat(buff, tmpS); } else if ((int)opt[i].min < _hestMax(opt[i].max)) { /* HEY scrutinize casts */ if (-1 == opt[i].max) { sprintf(tmpS, "%d\tor\tmore\t", opt[i].min); } else { sprintf(tmpS, "%d..%d\t", opt[i].min, _hestMax(opt[i].max)); } strcat(buff, tmpS); } } sprintf(tmpS, "%s%s", (airTypeEnum == opt[i].type ? opt[i].enm->name : (airTypeOther == opt[i].type ? opt[i].CB->type : airTypeStr[opt[i].type])), (_hestMax(opt[i].max) > 1 ? (airTypeOther == opt[i].type && 'y' == opt[i].CB->type[airStrlen(opt[i].CB->type)-1] && parm->cleverPluralizeOtherY ? "\bies" : "s") : "")); strcat(buff, tmpS); strcat(buff, ")"); } /* fprintf(stderr, "!%s: parm->elideSingleOtherDefault = %d\n", "hestGlossary", parm->elideSingleOtherDefault); */ if (opt[i].dflt && (opt[i].min || _hestMax(opt[i].max)) && (!( 2 == opt[i].kind && (airTypeFloat == opt[i].type || airTypeDouble == opt[i].type) && !AIR_EXISTS(airAtod(opt[i].dflt)) && parm->elideSingleNonExistFloatDefault )) && (!( (3 == opt[i].kind || 5 == opt[i].kind) && (airTypeFloat == opt[i].type || airTypeDouble == opt[i].type) && !AIR_EXISTS(airAtod(opt[i].dflt)) && parm->elideMultipleNonExistFloatDefault )) && (!( 2 == opt[i].kind && airTypeOther == opt[i].type && parm->elideSingleOtherDefault )) && (!( 2 == opt[i].kind && airTypeString == opt[i].type && parm->elideSingleEmptyStringDefault && 0 == airStrlen(opt[i].dflt) )) && (!( (3 == opt[i].kind || 5 == opt[i].kind) && airTypeString == opt[i].type && parm->elideMultipleEmptyStringDefault && 0 == airStrlen(opt[i].dflt) )) ) { /* if there are newlines in the info, then we want to clarify the default by printing it on its own line */ if (opt[i].info && strchr(opt[i].info, '\n')) { strcat(buff, "\n "); } else { strcat(buff, "; "); } strcat(buff, "default:\t"); strcpy(tmpS, opt[i].dflt); airStrtrans(tmpS, ' ', '\t'); strcat(buff, "\""); strcat(buff, tmpS); strcat(buff, "\""); } _hestPrintStr(f, maxlen + 3, maxlen + 3, parm->columns, buff, AIR_FALSE); } parm = !_parm ? hestParmFree(parm) : NULL; return; }
/* ** _nrrdSprintFieldInfo ** ** this prints "<prefix><field>: <info>" into *strP (after allocating it for ** big enough, usually with a stupidly big margin of error), in a form ** suitable to be written to NRRD or other image headers. This will always ** print something (for valid inputs), even stupid <info>s like ** "(unknown endian)". It is up to the caller to decide which fields ** are worth writing, via _nrrdFieldInteresting(). ** ** NOTE: some of these fields make sense in non-NRRD files (e.g. all ** the per-axis information), but many only make sense in NRRD files. ** This is just one example of NRRD-format-specific stuff that is not ** in formatNRRD.c */ void _nrrdSprintFieldInfo(char **strP, char *prefix, const Nrrd *nrrd, NrrdIoState *nio, int field) { char me[]="_nrrdSprintFieldInfo", buff[AIR_STRLEN_MED], *fnb; double colvec[NRRD_SPACE_DIM_MAX]; const char *fs; unsigned int ii, dd, uintStrlen = 11, size_tStrlen = 33, doubleStrlen = 513; int fslen, fdlen, endi, maxl; if (!( strP && prefix && nrrd && AIR_IN_CL(1, nrrd->dim, NRRD_DIM_MAX) && AIR_IN_OP(nrrdField_unknown, field, nrrdField_last) )) { return; } if (!_nrrdFieldInteresting(nrrd, nio, field)) { *strP = airStrdup(""); } fs = airEnumStr(nrrdField, field); fslen = strlen(prefix) + strlen(fs) + strlen(": ") + 1; switch (field) { case nrrdField_comment: case nrrdField_keyvalue: fprintf(stderr, "%s: CONFUSION: why are you calling me on \"%s\"?\n", me, airEnumStr(nrrdField, nrrdField_comment)); *strP = airStrdup(""); break; case nrrdField_content: airOneLinify(nrrd->content); *strP = (char *)calloc(fslen + strlen(nrrd->content), sizeof(char)); sprintf(*strP, "%s%s: %s", prefix, fs, nrrd->content); break; case nrrdField_number: *strP = (char *)calloc(fslen + size_tStrlen, sizeof(char)); sprintf(*strP, "%s%s: " _AIR_SIZE_T_CNV, prefix, fs, nrrdElementNumber(nrrd)); break; case nrrdField_type: *strP = (char *)calloc(fslen + strlen(airEnumStr(nrrdType, nrrd->type)), sizeof(char)); sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(nrrdType, nrrd->type)); break; case nrrdField_block_size: *strP = (char *)calloc(fslen + size_tStrlen, sizeof(char)); sprintf(*strP, "%s%s: " _AIR_SIZE_T_CNV, prefix, fs, nrrd->blockSize); break; case nrrdField_dimension: *strP = (char *)calloc(fslen + uintStrlen, sizeof(char)); sprintf(*strP, "%s%s: %d", prefix, fs, nrrd->dim); break; case nrrdField_space: *strP = (char *)calloc(fslen + strlen(airEnumStr(nrrdSpace, nrrd->space)), sizeof(char)); sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(nrrdSpace, nrrd->space)); break; case nrrdField_space_dimension: *strP = (char *)calloc(fslen + uintStrlen, sizeof(char)); sprintf(*strP, "%s%s: %d", prefix, fs, nrrd->spaceDim); break; /* ---- begin per-axis fields ---- */ case nrrdField_sizes: *strP = (char *)calloc(fslen + nrrd->dim*(size_tStrlen + 1), sizeof(char)); sprintf(*strP, "%s%s:", prefix, fs); for (ii=0; ii<nrrd->dim; ii++) { sprintf(buff, " " _AIR_SIZE_T_CNV, nrrd->axis[ii].size); strcat(*strP, buff); } break; case nrrdField_spacings: *strP = (char *)calloc(fslen + nrrd->dim*(doubleStrlen + 1), sizeof(char)); sprintf(*strP, "%s%s:", prefix, fs); for (ii=0; ii<nrrd->dim; ii++) { airSinglePrintf(NULL, buff, " %g", nrrd->axis[ii].spacing); strcat(*strP, buff); } break; case nrrdField_thicknesses: *strP = (char *)calloc(fslen + nrrd->dim*(doubleStrlen + 1), sizeof(char)); sprintf(*strP, "%s%s:", prefix, fs); for (ii=0; ii<nrrd->dim; ii++) { airSinglePrintf(NULL, buff, " %g", nrrd->axis[ii].thickness); strcat(*strP, buff); } break; case nrrdField_axis_mins: *strP = (char *)calloc(fslen + nrrd->dim*(doubleStrlen + 1), sizeof(char)); sprintf(*strP, "%s%s:", prefix, fs); for (ii=0; ii<nrrd->dim; ii++) { airSinglePrintf(NULL, buff, " %g", nrrd->axis[ii].min); strcat(*strP, buff); } break; case nrrdField_axis_maxs: *strP = (char *)calloc(fslen + nrrd->dim*(doubleStrlen + 1), sizeof(char)); sprintf(*strP, "%s%s:", prefix, fs); for (ii=0; ii<nrrd->dim; ii++) { airSinglePrintf(NULL, buff, " %g", nrrd->axis[ii].max); strcat(*strP, buff); } break; case nrrdField_space_directions: *strP = (char *)calloc(fslen + nrrd->dim*nrrd->spaceDim*(doubleStrlen + strlen("(,) ")), sizeof(char)); sprintf(*strP, "%s%s: ", prefix, fs); for (ii=0; ii<nrrd->dim; ii++) { _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim, nrrd->axis[ii].spaceDirection); if (ii < nrrd->dim-1) { strcat(*strP, " "); } } break; case nrrdField_centers: fdlen = 0; for (ii=0; ii<nrrd->dim; ii++) { fdlen += 1 + airStrlen(nrrd->axis[ii].center ? airEnumStr(nrrdCenter, nrrd->axis[ii].center) : NRRD_UNKNOWN); } *strP = (char *)calloc(fslen + fdlen, sizeof(char)); sprintf(*strP, "%s%s:", prefix, fs); for (ii=0; ii<nrrd->dim; ii++) { sprintf(buff, " %s", (nrrd->axis[ii].center ? airEnumStr(nrrdCenter, nrrd->axis[ii].center) : NRRD_UNKNOWN)); strcat(*strP, buff); } break; case nrrdField_kinds: fdlen = 0; for (ii=0; ii<nrrd->dim; ii++) { fdlen += 1 + airStrlen(nrrd->axis[ii].kind ? airEnumStr(nrrdKind, nrrd->axis[ii].kind) : NRRD_UNKNOWN); } *strP = (char *)calloc(fslen + fdlen, sizeof(char)); sprintf(*strP, "%s%s:", prefix, fs); for (ii=0; ii<nrrd->dim; ii++) { sprintf(buff, " %s", (nrrd->axis[ii].kind ? airEnumStr(nrrdKind, nrrd->axis[ii].kind) : NRRD_UNKNOWN)); strcat(*strP, buff); } break; case nrrdField_labels: fdlen = 0; for (ii=0; ii<nrrd->dim; ii++) { fdlen += airStrlen(nrrd->axis[ii].label) + 4; } *strP = (char *)calloc(fslen + fdlen, sizeof(char)); sprintf(*strP, "%s%s:", prefix, fs); for (ii=0; ii<nrrd->dim; ii++) { strcat(*strP, " \""); if (airStrlen(nrrd->axis[ii].label)) { strcat(*strP, nrrd->axis[ii].label); } strcat(*strP, "\""); } break; case nrrdField_units: fdlen = 0; for (ii=0; ii<nrrd->dim; ii++) { fdlen += airStrlen(nrrd->axis[ii].units) + 4; } *strP = (char *)calloc(fslen + fdlen, sizeof(char)); sprintf(*strP, "%s%s:", prefix, fs); for (ii=0; ii<nrrd->dim; ii++) { strcat(*strP, " \""); if (airStrlen(nrrd->axis[ii].units)) { strcat(*strP, nrrd->axis[ii].units); } strcat(*strP, "\""); } break; /* ---- end per-axis fields ---- */ case nrrdField_min: case nrrdField_max: /* we're basically a no-op, now that these fields became meaningless */ *strP = (char *)calloc(fslen + doubleStrlen, sizeof(char)); sprintf(*strP, "%s%s: 0.0", prefix, fs); strcat(*strP, buff); break; case nrrdField_old_min: *strP = (char *)calloc(fslen + doubleStrlen, sizeof(char)); sprintf(*strP, "%s%s: ", prefix, fs); airSinglePrintf(NULL, buff, "%g", nrrd->oldMin); strcat(*strP, buff); break; case nrrdField_old_max: *strP = (char *)calloc(fslen + doubleStrlen, sizeof(char)); sprintf(*strP, "%s%s: ", prefix, fs); airSinglePrintf(NULL, buff, "%g", nrrd->oldMax); strcat(*strP, buff); break; case nrrdField_endian: if (airEndianUnknown != nio->endian) { /* we know a specific endianness because either it was recorded as part of "unu make -h", or it was set (and data was possibly altered) as part of "unu save" */ endi = nio->endian; } else { /* we record our current architecture's endian because we're going to writing out data */ endi = AIR_ENDIAN; } *strP = (char *)calloc(fslen + strlen(airEnumStr(airEndian, endi)), sizeof(char)); sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(airEndian, endi)); break; case nrrdField_encoding: *strP = (char *)calloc(fslen + strlen(nio->encoding->name), sizeof(char)); sprintf(*strP, "%s%s: %s", prefix, fs, nio->encoding->name); break; case nrrdField_line_skip: *strP = (char *)calloc(fslen + uintStrlen, sizeof(char)); sprintf(*strP, "%s%s: %d", prefix, fs, nio->lineSkip); break; case nrrdField_byte_skip: *strP = (char *)calloc(fslen + uintStrlen, sizeof(char)); sprintf(*strP, "%s%s: %d", prefix, fs, nio->byteSkip); break; case nrrdField_sample_units: airOneLinify(nrrd->sampleUnits); *strP = (char *)calloc(fslen + strlen(nrrd->sampleUnits), sizeof(char)); sprintf(*strP, "%s%s: \"%s\"", prefix, fs, nrrd->sampleUnits); break; case nrrdField_space_units: fdlen = 0; for (ii=0; ii<nrrd->spaceDim; ii++) { fdlen += airStrlen(nrrd->spaceUnits[ii]) + 4; } *strP = (char *)calloc(fslen + fdlen, sizeof(char)); sprintf(*strP, "%s%s:", prefix, fs); for (ii=0; ii<nrrd->spaceDim; ii++) { strcat(*strP, " \""); if (airStrlen(nrrd->spaceUnits[ii])) { strcat(*strP, nrrd->spaceUnits[ii]); } strcat(*strP, "\""); } break; case nrrdField_space_origin: *strP = (char *)calloc(fslen + nrrd->spaceDim*(doubleStrlen + strlen("(,) ")), sizeof(char)); sprintf(*strP, "%s%s: ", prefix, fs); _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim, nrrd->spaceOrigin); break; case nrrdField_measurement_frame: *strP = (char *)calloc(fslen + (nrrd->spaceDim* nrrd->spaceDim*(doubleStrlen + strlen("(,) "))), sizeof(char)); sprintf(*strP, "%s%s: ", prefix, fs); for (dd=0; dd<nrrd->spaceDim; dd++) { for (ii=0; ii<nrrd->spaceDim; ii++) { colvec[ii] = nrrd->measurementFrame[dd][ii]; } _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim, colvec); if (dd < nrrd->spaceDim-1) { strcat(*strP, " "); } } break; case nrrdField_data_file: /* NOTE: this comes last (nrrdField_data_file is the highest-valued member of the nrrdField* enum) because the "LIST" form of the data file specification requires that the following lines be the filenames */ /* error checking elsewhere: assumes there is data file info */ if (nio->dataFNFormat) { *strP = (char *)calloc(fslen + strlen(nio->dataFNFormat) + 4*uintStrlen, sizeof(char)); if (nio->dataFileDim == nrrd->dim-1) { sprintf(*strP, "%s%s: %s %d %d %d", prefix, fs, nio->dataFNFormat, nio->dataFNMin, nio->dataFNMax, nio->dataFNStep); } else { sprintf(*strP, "%s%s: %s %d %d %d %d", prefix, fs, nio->dataFNFormat, nio->dataFNMin, nio->dataFNMax, nio->dataFNStep, nio->dataFileDim); } } else if (nio->dataFNArr->len > 1) { maxl = 0; for (ii=0; ii<nio->dataFNArr->len; ii++) { maxl = AIR_MAX(maxl, (int)strlen(nio->dataFN[ii])); } *strP = (char *)calloc(fslen + strlen(NRRD_LIST_FLAG) + uintStrlen + nio->dataFNArr->len * (maxl + 1), sizeof(char)); fnb = (char *)calloc(fslen + strlen(NRRD_LIST_FLAG) + uintStrlen + maxl + 1, sizeof(char)); if (nio->dataFileDim == nrrd->dim-1) { sprintf(*strP, "%s%s: LIST\n", prefix, fs); } else { sprintf(*strP, "%s%s: LIST %d\n", prefix, fs, nio->dataFileDim); } for (ii=0; ii<nio->dataFNArr->len; ii++) { sprintf(fnb, "%s%s", nio->dataFN[ii], ii<nio->dataFNArr->len-1 ? "\n" : ""); strcat(*strP, fnb); } free(fnb); } else { /* there is some ambiguity between a "LIST" of length one, and a single explicit data filename, but that's harmless */ *strP = (char *)calloc(fslen + strlen("./") + strlen(nio->dataFN[0]) + 1, sizeof(char)); sprintf(*strP, "%s%s: %s%s", prefix, fs, /* this is a favor to older readers that can deal with this NRRD file because its being saved in a NRRD0003 (or below) version, so we don't want to confuse them by not having the old explicit header-relative flag */ (_nrrdFormatNRRD_whichVersion(nrrd, nio) < 4 ? "./" : ""), nio->dataFN[0]); } break; default: fprintf(stderr, "%s: CONFUSION: field %d unrecognized\n", me, field); break; } return; }
/* ** _nrrdSprintFieldInfo ** ** this prints "<prefix><field>: <info>" into *strP (after allocating it for ** big enough, usually with a stupidly big margin of error), in a form ** suitable to be written to NRRD or other image headers. This will always ** print something (for valid inputs), even stupid <info>s like ** "(unknown endian)". It is up to the caller to decide which fields ** are worth writing, via _nrrdFieldInteresting(). ** ** NOTE: some of these fields make sense in non-NRRD files (e.g. all ** the per-axis information), but many only make sense in NRRD files. ** This is just one example of NRRD-format-specific stuff that is not ** in formatNRRD.c */ void _nrrdSprintFieldInfo(char **strP, const char *prefix, const Nrrd *nrrd, NrrdIoState *nio, int field) { static const char me[]="_nrrdSprintFieldInfo"; char buff[AIR_STRLEN_MED], *fnb, stmp[AIR_STRLEN_SMALL], *strtmp=NULL; double colvec[NRRD_SPACE_DIM_MAX]; const char *fs; unsigned int ii, dd, uintStrlen = 11, size_tStrlen = 33, doubleStrlen = 513; size_t fslen, fdlen, maxl; int endi; if (!( strP && prefix && nrrd && AIR_IN_CL(1, nrrd->dim, NRRD_DIM_MAX) && AIR_IN_OP(nrrdField_unknown, field, nrrdField_last) )) { return; } /* As of Sun Dec 2 01:57:48 CST 2012 (revision 5832) the only places where this function is called is when it has been guarded by "if (_nrrdFieldInteresting())" (except for in formatText.c when its called on the dimension field, which is always interesting). So, the following: if (!_nrrdFieldInteresting(nrrd, nio, field)) { *strP = airStrdup(""); } was redundant and confusingly created the appearance of a memory leak waiting to happen. We now let the default switch statement set *strP to NULL (all the other cases set it), to smoke out errors in how this function is called */ fs = airEnumStr(nrrdField, field); fslen = strlen(prefix) + strlen(fs) + strlen(": ") + 1; switch (field) { case nrrdField_comment: case nrrdField_keyvalue: fprintf(stderr, "%s: CONFUSION: why are you calling me on \"%s\"?\n", me, airEnumStr(nrrdField, nrrdField_comment)); *strP = airStrdup(""); break; case nrrdField_content: strtmp = airOneLinify(airStrdup(nrrd->content)); *strP = AIR_CALLOC(fslen + strlen(strtmp), char); sprintf(*strP, "%s%s: %s", prefix, fs, strtmp); airFree(strtmp); strtmp = NULL; break; case nrrdField_number: *strP = AIR_CALLOC(fslen + size_tStrlen, char); sprintf(*strP, "%s%s: %s", prefix, fs, airSprintSize_t(stmp, nrrdElementNumber(nrrd))); break; case nrrdField_type: *strP = AIR_CALLOC(fslen + strlen(airEnumStr(nrrdType, nrrd->type)), char); sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(nrrdType, nrrd->type)); break; case nrrdField_block_size: *strP = AIR_CALLOC(fslen + size_tStrlen, char); sprintf(*strP, "%s%s: %s", prefix, fs, airSprintSize_t(stmp, nrrd->blockSize)); break; case nrrdField_dimension: *strP = AIR_CALLOC(fslen + uintStrlen, char); sprintf(*strP, "%s%s: %d", prefix, fs, nrrd->dim); break; case nrrdField_space: *strP = AIR_CALLOC(fslen + strlen(airEnumStr(nrrdSpace, nrrd->space)), char); sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(nrrdSpace, nrrd->space)); break; case nrrdField_space_dimension: *strP = AIR_CALLOC(fslen + uintStrlen, char); sprintf(*strP, "%s%s: %d", prefix, fs, nrrd->spaceDim); break; /* ---- begin per-axis fields ---- */ case nrrdField_sizes: *strP = AIR_CALLOC(fslen + nrrd->dim*(size_tStrlen + 1), char); sprintf(*strP, "%s%s:", prefix, fs); for (ii=0; ii<nrrd->dim; ii++) { sprintf(buff, " %s", airSprintSize_t(stmp, nrrd->axis[ii].size)); strcat(*strP, buff); } break; case nrrdField_spacings: *strP = AIR_CALLOC(fslen + nrrd->dim*(doubleStrlen + 1), char); sprintf(*strP, "%s%s:", prefix, fs); for (ii=0; ii<nrrd->dim; ii++) { airSinglePrintf(NULL, buff, " %.17g", nrrd->axis[ii].spacing); strcat(*strP, buff); } break; case nrrdField_thicknesses: *strP = AIR_CALLOC(fslen + nrrd->dim*(doubleStrlen + 1), char); sprintf(*strP, "%s%s:", prefix, fs); for (ii=0; ii<nrrd->dim; ii++) { airSinglePrintf(NULL, buff, " %.17g", nrrd->axis[ii].thickness); strcat(*strP, buff); } break; case nrrdField_axis_mins: *strP = AIR_CALLOC(fslen + nrrd->dim*(doubleStrlen + 1), char); sprintf(*strP, "%s%s:", prefix, fs); for (ii=0; ii<nrrd->dim; ii++) { airSinglePrintf(NULL, buff, " %.17g", nrrd->axis[ii].min); strcat(*strP, buff); } break; case nrrdField_axis_maxs: *strP = AIR_CALLOC(fslen + nrrd->dim*(doubleStrlen + 1), char); sprintf(*strP, "%s%s:", prefix, fs); for (ii=0; ii<nrrd->dim; ii++) { airSinglePrintf(NULL, buff, " %.17g", nrrd->axis[ii].max); strcat(*strP, buff); } break; case nrrdField_space_directions: *strP = AIR_CALLOC(fslen + nrrd->dim*nrrd->spaceDim*(doubleStrlen + strlen("(,) ")), char); sprintf(*strP, "%s%s: ", prefix, fs); for (ii=0; ii<nrrd->dim; ii++) { _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim, nrrd->axis[ii].spaceDirection); if (ii < nrrd->dim-1) { strcat(*strP, " "); } } break; case nrrdField_centers: fdlen = 0; for (ii=0; ii<nrrd->dim; ii++) { fdlen += 1 + airStrlen(nrrd->axis[ii].center ? airEnumStr(nrrdCenter, nrrd->axis[ii].center) : NRRD_UNKNOWN); } *strP = AIR_CALLOC(fslen + fdlen, char); sprintf(*strP, "%s%s:", prefix, fs); for (ii=0; ii<nrrd->dim; ii++) { sprintf(buff, " %s", (nrrd->axis[ii].center ? airEnumStr(nrrdCenter, nrrd->axis[ii].center) : NRRD_UNKNOWN)); strcat(*strP, buff); } break; case nrrdField_kinds: fdlen = 0; for (ii=0; ii<nrrd->dim; ii++) { fdlen += 1 + airStrlen(nrrd->axis[ii].kind ? airEnumStr(nrrdKind, nrrd->axis[ii].kind) : NRRD_UNKNOWN); } *strP = AIR_CALLOC(fslen + fdlen, char); sprintf(*strP, "%s%s:", prefix, fs); for (ii=0; ii<nrrd->dim; ii++) { sprintf(buff, " %s", (nrrd->axis[ii].kind ? airEnumStr(nrrdKind, nrrd->axis[ii].kind) : NRRD_UNKNOWN)); strcat(*strP, buff); } break; case nrrdField_labels: case nrrdField_units: #define LABEL_OR_UNITS (nrrdField_labels == field \ ? nrrd->axis[ii].label \ : nrrd->axis[ii].units) fdlen = 0; for (ii=0; ii<nrrd->dim; ii++) { /* The "2*" is because at worst every character needs escaping. The "+ 3" for the |" "| between each part */ fdlen += 2*airStrlen(LABEL_OR_UNITS) + 3; } fdlen += 1; /* for '\0' */ *strP = AIR_CALLOC(fslen + fdlen, char); sprintf(*strP, "%s%s:", prefix, fs); for (ii=0; ii<nrrd->dim; ii++) { strcat(*strP, " \""); if (airStrlen(nrrd->axis[ii].label)) { _nrrdWriteEscaped(NULL, *strP, LABEL_OR_UNITS, "\"", _NRRD_WHITESPACE_NOTAB); } strcat(*strP, "\""); } #undef LABEL_OR_UNITS break; /* ---- end per-axis fields ---- */ case nrrdField_min: case nrrdField_max: /* we're basically a no-op, now that these fields became meaningless */ *strP = AIR_CALLOC(fslen + doubleStrlen, char); sprintf(*strP, "%s%s: 0.0", prefix, fs); strcat(*strP, buff); break; case nrrdField_old_min: *strP = AIR_CALLOC(fslen + doubleStrlen, char); sprintf(*strP, "%s%s: ", prefix, fs); airSinglePrintf(NULL, buff, "%.17g", nrrd->oldMin); strcat(*strP, buff); break; case nrrdField_old_max: *strP = AIR_CALLOC(fslen + doubleStrlen, char); sprintf(*strP, "%s%s: ", prefix, fs); airSinglePrintf(NULL, buff, "%.17g", nrrd->oldMax); strcat(*strP, buff); break; case nrrdField_endian: if (airEndianUnknown != nio->endian) { /* we know a specific endianness because either it was recorded as part of "unu make -h", or it was set (and data was possibly altered) as part of "unu save" */ endi = nio->endian; } else { /* we record our current architecture's endian because we're going to writing out data */ endi = airMyEndian(); } *strP = AIR_CALLOC(fslen + strlen(airEnumStr(airEndian, endi)), char); sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(airEndian, endi)); break; case nrrdField_encoding: *strP = AIR_CALLOC(fslen + strlen(nio->encoding->name), char); sprintf(*strP, "%s%s: %s", prefix, fs, nio->encoding->name); break; case nrrdField_line_skip: *strP = AIR_CALLOC(fslen + uintStrlen, char); sprintf(*strP, "%s%s: %d", prefix, fs, nio->lineSkip); break; case nrrdField_byte_skip: *strP = AIR_CALLOC(fslen + uintStrlen, char); sprintf(*strP, "%s%s: %ld", prefix, fs, nio->byteSkip); break; case nrrdField_sample_units: strtmp = airOneLinify(airStrdup(nrrd->sampleUnits)); *strP = AIR_CALLOC(fslen + strlen(strtmp), char); sprintf(*strP, "%s%s: \"%s\"", prefix, fs, strtmp); airFree(strtmp); strtmp = NULL; break; case nrrdField_space_units: fdlen = 0; for (ii=0; ii<nrrd->spaceDim; ii++) { /* The "2*" is because at worst every character needs escaping. See note in formatNRRD.c about how even though its not part of the format, we have worst-case scenario of having to escape a space units which is nothing but ". The "+ 3" for the |" "| between each part */ fdlen += 2*airStrlen(nrrd->spaceUnits[ii]) + 3; } fdlen += 1; /* for '\0' */ *strP = AIR_CALLOC(fslen + fdlen, char); sprintf(*strP, "%s%s:", prefix, fs); for (ii=0; ii<nrrd->spaceDim; ii++) { strcat(*strP, " \""); if (airStrlen(nrrd->spaceUnits[ii])) { _nrrdWriteEscaped(NULL, *strP, nrrd->spaceUnits[ii], "\"", _NRRD_WHITESPACE_NOTAB); } strcat(*strP, "\""); } break; case nrrdField_space_origin: *strP = AIR_CALLOC(fslen + nrrd->spaceDim*(doubleStrlen + strlen("(,) ")), char); sprintf(*strP, "%s%s: ", prefix, fs); _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim, nrrd->spaceOrigin); break; case nrrdField_measurement_frame: *strP = AIR_CALLOC(fslen + (nrrd->spaceDim* nrrd->spaceDim*(doubleStrlen + strlen("(,) "))), char); sprintf(*strP, "%s%s: ", prefix, fs); for (dd=0; dd<nrrd->spaceDim; dd++) { for (ii=0; ii<nrrd->spaceDim; ii++) { colvec[ii] = nrrd->measurementFrame[dd][ii]; } _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim, colvec); if (dd < nrrd->spaceDim-1) { strcat(*strP, " "); } } break; case nrrdField_data_file: /* NOTE: this comes last (nrrdField_data_file is the highest-valued member of the nrrdField* enum) because the "LIST" form of the data file specification requires that the following lines be the filenames */ /* error checking elsewhere: assumes there is data file info */ if (nio->dataFNFormat) { *strP = AIR_CALLOC(fslen + strlen(nio->dataFNFormat) + 4*uintStrlen, char); if (nio->dataFileDim == nrrd->dim-1) { sprintf(*strP, "%s%s: %s %d %d %d", prefix, fs, nio->dataFNFormat, nio->dataFNMin, nio->dataFNMax, nio->dataFNStep); } else { sprintf(*strP, "%s%s: %s %d %d %d %u", prefix, fs, nio->dataFNFormat, nio->dataFNMin, nio->dataFNMax, nio->dataFNStep, nio->dataFileDim); } } else if (nio->dataFNArr->len > 1) {