GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: Testing/nrrd/tskip.c Lines: 87 140 62.1 %
Date: 2017-05-26 Branches: 32 64 50.0 %

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 "teem/nrrd.h"
25
26
#define BKEY "tskip"
27
28
#if defined(WIN32) || defined(_WIN32)
29
#  define COMMIT "c"
30
#else
31
#  define COMMIT ""
32
#endif
33
34
/*
35
** Tests:
36
** nrrdLoad with positive and negative byte skipping on data read,
37
** with nrrdEncodingRaw
38
*/
39
40
static const char *tskipInfo = "for testing byte skipping in nrrd files";
41
42
int
43
main(int argc, const char **argv) {
44
  /* stock variables */
45
12
  char me[] = BKEY;
46
6
  hestOpt *hopt=NULL;
47
  hestParm *hparm;
48
  airArray *mop;
49
  /* variables specific to this program */
50
6
  int negskip, progress;
51
  Nrrd *nref, *nin;
52
6
  size_t *size, ii, nn, tick, pad[2];
53
6
  unsigned int axi, refCRC, gotCRC, sizeNum;
54
6
  char *berr, *outS[2], stmp[AIR_STRLEN_SMALL], doneStr[AIR_STRLEN_SMALL];
55
  airRandMTState *rng;
56
6
  unsigned int seed, *rdata, printbytes;
57
  unsigned char *dataUC;
58
  double time0, time1;
59
  FILE *fout;
60
61
  /* start-up */
62
6
  mop = airMopNew();
63
6
  hparm = hestParmNew();
64
6
  airMopAdd(mop, hparm, (airMopper)hestParmFree, airMopAlways);
65
  /* learn things from hest */
66
6
  hestOptAdd(&hopt, "seed", "N", airTypeUInt, 1, 1, &seed, "42",
67
             "seed for RNG");
68
6
  hestOptAdd(&hopt, "s", "sz0", airTypeSize_t, 1, -1, &size, NULL,
69
             "sizes of desired output", &sizeNum);
70
6
  hestOptAdd(&hopt, "p", "pb pa", airTypeSize_t, 2, 2, pad, "0 0",
71
             "bytes of padding before, and after, the data segment "
72
             "in the written data");
73
6
  hestOptAdd(&hopt, "ns", "bool", airTypeInt, 0, 0, &negskip, NULL,
74
             "skipping should be relative to end of file");
75
6
  hestOptAdd(&hopt, "pb", "print", airTypeUInt, 1, 1, &printbytes, "0",
76
             "bytes to print at beginning and end of data, to help "
77
             "debug problems");
78
6
  hestOptAdd(&hopt, "o", "out.data out.nhdr", airTypeString, 2, 2,
79
6
             outS, NULL, "output filenames of data and header");
80
6
  hestParseOrDie(hopt, argc-1, argv+1, hparm, me, tskipInfo,
81
                 AIR_TRUE, AIR_TRUE, AIR_TRUE);
82
6
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
83
6
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);
84
85
  /* generate reference nrrd data */
86
6
  nref = nrrdNew();
87
6
  airMopAdd(mop, nref, (airMopper)nrrdNuke, airMopAlways);
88
6
  if (nrrdMaybeAlloc_nva(nref, nrrdTypeUInt, sizeNum, size)) {
89
    airMopAdd(mop, berr=biffGetDone(NRRD), airFree, airMopAlways);
90
    fprintf(stderr, "%s: error allocating data: %s\n", me, berr);
91
    airMopError(mop); return 1;
92
  }
93
6
  rng = airRandMTStateNew(seed);
94
6
  airMopAdd(mop, rng, (airMopper)airRandMTStateNix, airMopAlways);
95
6
  nn = nrrdElementNumber(nref);
96
6
  rdata = AIR_CAST(unsigned int *, nref->data);
97
6
  fprintf(stderr, "generating data: . . .       "); fflush(stderr);
98
6
  time0 = airTime();
99
  progress = AIR_FALSE;
100
6
  tick = nn/100;
101
12733284
  for (ii=0; ii<nn; ii++) {
102
6366636
    rdata[ii] = airUIrandMT_r(rng);
103

12733266
    if (ii && tick && !(ii % tick)) {
104
600
      time1 = airTime();
105
600
      if (time1 - time0 > 1.0) {
106
        /* if it took more than a second to do 1% of the thing,
107
           would be good to generate some progress indication */
108
        progress = AIR_TRUE;
109
      }
110
600
      if (progress) {
111
        fprintf(stderr, "%s", airDoneStr(0, ii, nn, doneStr)); fflush(stderr);
112
      }
113
    }
114
  }
115

12
  if (progress) {
116
6
    fprintf(stderr, "%s\n", airDoneStr(0, ii, nn, doneStr)); fflush(stderr);
117
  } else {
118
6
    fprintf(stderr, "\n");
119
  }
120
6
  fprintf(stderr, "finding reference (big-endian) CRC: "); fflush(stderr);
121
6
  refCRC = nrrdCRC32(nref, airEndianBig);
122
6
  fprintf(stderr, "%u\n", refCRC);
123
124
  /* write data, with padding */
125
6
  fprintf(stderr, "saving data . . . "); fflush(stderr);
126
6
  if (!(fout = fopen(outS[0], "wb" COMMIT))) {
127
    fprintf(stderr, "\n%s: couldn't open %s for writing: %s\n", me,
128
            outS[0], strerror(errno));
129
    airMopError(mop); return 1;
130
  }
131
6
  airMopAdd(mop, fout, (airMopper)airFclose, airMopAlways);
132
584
  for (ii=0; ii<pad[0]; ii++) {
133
286
    if (EOF == fputc(1, fout)) {
134
      fprintf(stderr, "\n%s: error doing pre-padding\n", me);
135
      airMopError(mop); return 1;
136
    }
137
  }
138
6
  if (nn != fwrite(nref->data, nrrdElementSize(nref), nn, fout)) {
139
    fprintf(stderr, "\n%s: error writing data\n", me);
140
    airMopError(mop); return 1;
141
  }
142
732
  for (ii=0; ii<pad[1]; ii++) {
143
360
    if (EOF == fputc(2, fout)) {
144
      fprintf(stderr, "\n%s: error doing post-padding\n", me);
145
      airMopError(mop); return 1;
146
    }
147
  }
148
6
  if (EOF == fflush(fout)) {
149
    fprintf(stderr, "\n%s: error fflushing data: %s\n", me,
150
            strerror(errno));
151
  }
152
6
  fprintf(stderr, "\n");
153
6
  if (printbytes) {
154
    size_t bi, rpb, local_nn;
155
    char local_stmp[AIR_STRLEN_SMALL];
156
    local_nn = nrrdElementSize(nref)*nrrdElementNumber(nref);
157
    rpb = AIR_MIN(printbytes, local_nn);
158
    dataUC = AIR_CAST(unsigned char *, nref->data);
159
    fprintf(stderr, "CORRECT %s bytes at beginning:\n",
160
            airSprintSize_t(local_stmp, rpb));
161
    for (bi=0; bi<rpb; bi++) {
162
      fprintf(stderr, "%x ", dataUC[bi]);
163
    }
164
    fprintf(stderr, "...\n");
165
    fprintf(stderr, "CORRECT %s bytes at end:\n",
166
            airSprintSize_t(local_stmp, rpb));
167
    fprintf(stderr, "...");
168
    for (bi=local_nn - rpb; bi<local_nn; bi++) {
169
      fprintf(stderr, " %x", dataUC[bi]);
170
    }
171
    fprintf(stderr, "\n");
172
  }
173
6
  airMopSingleOkay(mop, fout);
174
6
  airMopSingleOkay(mop, nref); nref = NULL;
175
176
  /* write header; for now just writing the header directly */
177
6
  fprintf(stderr, "writing header . . . \n");
178
6
  if (!(fout = fopen(outS[1], "w"))) {
179
    fprintf(stderr, "%s: couldn't open %s for writing: %s\n", me,
180
            outS[1], strerror(errno));
181
    airMopError(mop); return 1;
182
  }
183
6
  airMopAdd(mop, fout, (airMopper)airFclose, airMopAlways);
184
6
  fprintf(fout, "NRRD0005\n");
185
6
  fprintf(fout, "type: unsigned int\n");
186
6
  fprintf(fout, "dimension: %u\n", sizeNum);
187
6
  fprintf(fout, "sizes:");
188
48
  for (axi=0; axi<sizeNum; axi++) {
189
18
    fprintf(fout, " %s", airSprintSize_t(stmp, size[axi]));
190
  }
191
6
  fprintf(fout, "\n");
192
6
  fprintf(fout, "endian: %s\n", airEnumStr(airEndian, airMyEndian()));
193
6
  fprintf(fout, "encoding: %s\n", airEnumStr(nrrdEncodingType,
194
                                             nrrdEncodingTypeRaw));
195
6
  if (!negskip) {
196
3
    if (pad[0]) {
197
2
      fprintf(fout, "byte skip: %s\n", airSprintSize_t(stmp, pad[0]));
198
2
    }
199
  } else {
200
3
    fprintf(fout, "byte skip: -%s\n", airSprintSize_t(stmp, pad[1]+1));
201
  }
202
6
  fprintf(fout, "data file: %s\n", outS[0]);
203
6
  airMopSingleOkay(mop, fout);
204
205
  /* read it in, make sure it checks out */
206
6
  fprintf(stderr, "reading data . . . \n");
207
6
  nin = nrrdNew();
208
6
  airMopAdd(mop, nin, (airMopper)nrrdNuke, airMopAlways);
209
6
  if (nrrdLoad(nin, outS[1], NULL)) {
210
    airMopAdd(mop, berr=biffGetDone(NRRD), airFree, airMopAlways);
211
    fprintf(stderr, "%s: error reading back in: %s\n", me, berr);
212
    airMopError(mop); return 1;
213
  }
214
6
  if (printbytes) {
215
    size_t bi, rpb, local_nn;
216
    char local_stmp[AIR_STRLEN_SMALL];
217
    local_nn = nrrdElementSize(nin)*nrrdElementNumber(nin);
218
    rpb = AIR_MIN(printbytes, local_nn);
219
    dataUC = AIR_CAST(unsigned char *, nin->data);
220
    fprintf(stderr, "FOUND %s bytes at beginning:\n",
221
            airSprintSize_t(local_stmp, rpb));
222
    for (bi=0; bi<rpb; bi++) {
223
      fprintf(stderr, "%x ", dataUC[bi]);
224
    }
225
    fprintf(stderr, "...\n");
226
    fprintf(stderr, "FOUND %s bytes at end:\n",
227
            airSprintSize_t(local_stmp, rpb));
228
    fprintf(stderr, "...");
229
    for (bi=local_nn - rpb; bi<local_nn; bi++) {
230
      fprintf(stderr, " %x", dataUC[bi]);
231
    }
232
    fprintf(stderr, "\n");
233
  }
234
6
  fprintf(stderr, "finding new CRC . . . \n");
235
6
  gotCRC = nrrdCRC32(nin, airEndianBig);
236

12
  if (refCRC != gotCRC) {
237
6
    fprintf(stderr, "%s: got CRC %u but wanted %u\n", me, gotCRC, refCRC);
238
    airMopError(mop); return 1;
239
  }
240
6
  fprintf(stderr, "(all ok)\n");
241
242
  /* HEY: to test gzip reading, we really want to do a system call to
243
     gzip compress the data, and write a new header to point to the
244
     compressed data, and make sure we can read in that just the same */
245
246
6
  airMopOkay(mop);
247
6
  return 0;
248
6
}