/* ******** nrrdNix() ** ** does nothing with the array data inside, just does whatever is needed ** to free the nrrd itself ** ** returns NULL ** ** this does NOT use biff */ Nrrd * nrrdNix(Nrrd *nrrd) { int ii; if (nrrd) { for (ii=0; ii<NRRD_DIM_MAX; ii++) { _nrrdAxisInfoInit(&(nrrd->axis[ii])); } for (ii=0; ii<NRRD_SPACE_DIM_MAX; ii++) { nrrd->spaceUnits[ii] = (char *)airFree(nrrd->spaceUnits[ii]); } nrrd->content = (char *)airFree(nrrd->content); nrrd->sampleUnits = (char *)airFree(nrrd->sampleUnits); nrrdCommentClear(nrrd); nrrd->cmtArr = airArrayNix(nrrd->cmtArr); nrrdKeyValueClear(nrrd); nrrd->kvpArr = airArrayNix(nrrd->kvpArr); airFree(nrrd); } return NULL; }
int miteRayEnd(miteThread *mtt, miteRender *mrr, miteUser *muu) { int idx, slen, stageIdx; mite_t *imgData; double A; AIR_UNUSED(mrr); mtt->samples += mtt->raySample; idx = mtt->ui + (muu->nout->axis[1].size)*mtt->vi; imgData = (mite_t*)muu->nout->data; A = 1 - mtt->TT; if (A) { ELL_5V_SET(imgData + 5*idx, mtt->RR/A, mtt->GG/A, mtt->BB/A, A, mtt->ZZ); } else { ELL_5V_SET(imgData + 5*idx, 0, 0, 0, 0, AIR_NAN); } if (mtt->verbose) { /* muu->debug may be over-allocated, but that's harmless */ muu->ndebug->axis[1].size = mtt->raySample; nrrdWrap_va(muu->ndebug, muu->debug, nrrdTypeDouble, 2, AIR_CAST(size_t, muu->ndebug->axis[0].size), AIR_CAST(size_t, mtt->raySample)); airArrayNix(muu->debugArr); slen = 0; for (stageIdx=0; stageIdx<mtt->stageNum; stageIdx++) { slen += strlen(mtt->stage[stageIdx].label) + 2; } slen += strlen("R,G,B,A,Z") + 1; muu->ndebug->axis[0].label = (char *)calloc(slen, sizeof(char)); for (stageIdx=0; stageIdx<mtt->stageNum; stageIdx++) { strcat(muu->ndebug->axis[0].label, mtt->stage[stageIdx].label); strcat(muu->ndebug->axis[0].label, ",,"); } strcat(muu->ndebug->axis[0].label, "R,G,B,A,Z"); } return 0; }
int main(int argc, char *argv[]) { char *me, *fname, *incrS; airArray *mop, *dataArr; FILE *file; unsigned int incr, numRed; unsigned char *data; int datum; /* must be int, so it can store EOF */ airPtrPtrUnion appu; me = argv[0]; if (3 != argc) { /* 0 1 2 (3) */ fprintf(stderr, "usage: %s <filename> <incr>\n", me); return 1; } fname = argv[1]; incrS = argv[2]; /* the "mop" is for management of dynamically allocated resources cleanly in combination with error handling, its not important for understanding how airArrays work (although as you can tell from the declaration, the "mop" is built on an airArray) */ mop = airMopNew(); if (!(file = fopen(fname, "rb"))) { fprintf(stderr, "%s: couldn't open %s for reading\n", me, fname); airMopError(mop); return 1; } airMopAdd(mop, file, (airMopper)airFclose, airMopAlways); if (1 != sscanf(incrS, "%ud", &incr)) { fprintf(stderr, "%s: couln't parse incr \"%s\" as unsigned int\n", me, incrS); airMopError(mop); return 1; } /* now "file" is the open file that we read from, and "incr is the size increment (the granularity) for re-allocating the data */ /* the arguments here are as follows: 1) &data: the address of the array (itself a pointer) into which we'll copy the data. Whenever the airArray re-allocates the array, it will update the value of the array variable to the new location. So, while it seems a little weird at first, the value of the "data" variable can change as a side-effect of calling the airArray functions. 2) NULL: we could pass the address of a variable to record the current allocated length of the array, and this might be useful, but isn't necessary 3) sizeof(unsigned char): this is the size of the individual elements that we are saving in the array. Because memory is allocated and addressed at the level of individual bytes (and files can be read one byte at-a-time), we manage the buffer as an array of unsigned chars. 4) incr: when the array length is a multiple of incr, the memory segment is re-allocated, so this determines how often the re-allocation happens (we want it to happen fairly infrequently) */ /* dataArr = airArrayNew(&data, NULL, sizeof(unsigned char), incr); */ /* but wait: to play well with type checking, we have to use a stupid union to pass in the address of the array. So, appu.v == &data, but the types are right. We don't do a cast because recent versions of gcc will complain about breaking "strict-aliasing rules". */ appu.uc = &data; dataArr = airArrayNew(appu.v, NULL, sizeof(unsigned char), incr); if (!dataArr) { fprintf(stderr, "%s: couldn't allocate airArray\n", me); airMopError(mop); return 1; } /* numRed will keep track of the number of bytes that have been successfully read from the file AND stored in data[] */ numRed = 0; /* try to get the first byte of data */ datum = fgetc(file); if (EOF == datum) { fprintf(stderr, "%s: hit EOF trying to get first byte\n", me); airMopError(mop); return 1; } while (EOF != datum) { airArrayLenSet(dataArr, numRed+1); if (!data) { fprintf(stderr, "%s: couldn't re-allocated data buffer\n", me); airMopError(mop); return 1; } /* now "data" is the address of a sufficiently large array */ data[numRed++] = datum; datum = fgetc(file); } /* loop finishes when there's nothing more to read from file */ printf("%s: read %u bytes into memory\n", me, numRed); /* destroy the airArray, but keep the data allocated */ airArrayNix(dataArr); printf("%s: first value was %u\n", me, data[0]); /* free up the data array itself */ free(data); airMopOkay(mop); return 0; }