GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/nrrd/hestNrrd.c Lines: 7 102 6.9 %
Date: 2017-05-26 Branches: 2 65 3.1 %

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 "nrrd.h"
25
#include "privateNrrd.h"
26
27
/* ---------------------------- Nrrd ----------------------------- */
28
29
/*
30
** _nrrdHestNrrdParse()
31
**
32
** Converts a filename into a nrrd for the sake of hest.
33
** There is no HestMaybeNrrdParse because this already does that:
34
** when we get an empty string, we give back a NULL pointer, and
35
** that is just fine
36
*/
37
int
38
_nrrdHestNrrdParse(void *ptr, char *str, char err[AIR_STRLEN_HUGE]) {
39
  char me[] = "_nrrdHestNrrdParse", *nerr;
40
  Nrrd **nrrdP;
41
  airArray *mop;
42
43
  if (!(ptr && str)) {
44
    sprintf(err, "%s: got NULL pointer", me);
45
    return 1;
46
  }
47
  nrrdP = (Nrrd **)ptr;
48
  if (airStrlen(str)) {
49
    mop = airMopNew();
50
    *nrrdP = nrrdNew();
51
    airMopAdd(mop, *nrrdP, (airMopper)nrrdNuke, airMopOnError);
52
    if (nrrdLoad(*nrrdP, str, NULL)) {
53
      airMopAdd(mop, nerr = biffGetDone(NRRD), airFree, airMopOnError);
54
      airStrcpy(err, AIR_STRLEN_HUGE, nerr);
55
      airMopError(mop);
56
      return (strstr(err, "EOF") ? 2 : 1);
57
    }
58
    airMopOkay(mop);
59
  } else {
60
    /* they gave us an empty string, we give back no nrrd,
61
       but its not an error condition */
62
    *nrrdP = NULL;
63
  }
64
  return 0;
65
}
66
67
hestCB
68
_nrrdHestNrrd = {
69
  sizeof(Nrrd *),
70
  "nrrd",
71
  _nrrdHestNrrdParse,
72
  (airMopper)nrrdNuke
73
};
74
75
hestCB *
76
nrrdHestNrrd = &_nrrdHestNrrd;
77
78
/* ------------------------ NrrdKernelSpec -------------------------- */
79
80
int
81
_nrrdHestKernelSpecParse(void *ptr, char *str, char err[AIR_STRLEN_HUGE]) {
82
  NrrdKernelSpec **ksP;
83
  char me[]="_nrrdHestKernelSpecParse", *nerr;
84
85
  if (!(ptr && str)) {
86
    sprintf(err, "%s: got NULL pointer", me);
87
    return 1;
88
  }
89
  ksP = (NrrdKernelSpec **)ptr;
90
  *ksP = nrrdKernelSpecNew();
91
  if (nrrdKernelParse(&((*ksP)->kernel), (*ksP)->parm, str)) {
92
    nerr = biffGetDone(NRRD);
93
    airStrcpy(err, AIR_STRLEN_HUGE, nerr);
94
    free(nerr);
95
    return 1;
96
  }
97
  return 0;
98
}
99
100
hestCB
101
_nrrdHestKernelSpec = {
102
  sizeof(NrrdKernelSpec*),
103
  "kernel specification",
104
  _nrrdHestKernelSpecParse,
105
  (airMopper)nrrdKernelSpecNix
106
};
107
108
hestCB *
109
nrrdHestKernelSpec = &_nrrdHestKernelSpec;
110
111
/* ------------------------ NrrdBoundarySpec -------------------------- */
112
113
int
114
_nrrdHestBoundarySpecParse(void *ptr, char *str, char err[AIR_STRLEN_HUGE]) {
115
  NrrdBoundarySpec **bsp;
116
6
  char me[]="_nrrdHestBoundarySpecParse", *nerr;
117
118
3
  if (!(ptr && str)) {
119
    sprintf(err, "%s: got NULL pointer", me);
120
    return 1;
121
  }
122
3
  bsp = (NrrdBoundarySpec **)ptr;
123
3
  *bsp = nrrdBoundarySpecNew();
124
3
  if (nrrdBoundarySpecParse(*bsp, str)) {
125
    nerr = biffGetDone(NRRD);
126
    airStrcpy(err, AIR_STRLEN_HUGE, nerr);
127
    /* HEY: why not freeing bsp? */
128
    free(nerr);
129
    return 1;
130
  }
131
3
  return 0;
132
3
}
133
134
hestCB
135
_nrrdHestBoundarySpec = {
136
  sizeof(NrrdBoundarySpec*),
137
  "boundary specification",
138
  _nrrdHestBoundarySpecParse,
139
  (airMopper)nrrdBoundarySpecNix
140
};
141
142
hestCB *
143
nrrdHestBoundarySpec = &_nrrdHestBoundarySpec;
144
145
/* --------------------------- NrrdIter ----------------------------- */
146
147
int
148
_nrrdLooksLikeANumber(char *str) {
149
  /* 0: -+                (no restriction, but that's a little daft)
150
     1: 0123456789        n > 0
151
     2: .                 0 <= n <= 1
152
     3: eE                0 <= n <= 1
153
     4: everything else   0 == n
154
  */
155
  int count[5];
156
157
  count[0] = count[1] = count[2] = count[3] = count[4] = 0;
158
  while (*str) {
159
    int lwc, cc = *str;
160
    lwc = tolower(cc);
161
    switch (lwc) {
162
    case '-': case '+':
163
      count[0]++;
164
      break;
165
    case '0': case '1': case '2': case '3': case '4':
166
    case '5': case '6': case '7': case '8': case '9':
167
      count[1]++;
168
      break;
169
    case '.':
170
      count[2]++;
171
      break;
172
    case 'e':
173
      count[3]++;
174
      break;
175
    default:
176
      count[4]++;
177
      break;
178
    }
179
    str++;
180
  }
181
  if (count[1] > 0 &&
182
      AIR_IN_CL(0, count[2], 1) &&
183
      AIR_IN_CL(0, count[3], 1) &&
184
      count[4] == 0) {
185
    return AIR_TRUE;
186
  } else {
187
    return AIR_FALSE;
188
  }
189
}
190
191
int
192
_nrrdHestIterParse(void *ptr, char *str, char err[AIR_STRLEN_HUGE]) {
193
  char me[]="_nrrdHestIterParse", *nerr;
194
  Nrrd *nrrd;
195
  NrrdIter **iterP;
196
  airArray *mop;
197
  double val;
198
  int ret;
199
200
  if (!(ptr && str)) {
201
    sprintf(err, "%s: got NULL pointer", me);
202
    return 1;
203
  }
204
  iterP = (NrrdIter **)ptr;
205
  mop = airMopNew();
206
  *iterP = nrrdIterNew();
207
  airMopAdd(mop, *iterP, (airMopper)nrrdIterNix, airMopOnError);
208
209
  /* the challenge here is determining if a given string represents a
210
     filename or a number.  Obviously there are cases where it could
211
     be both, so we'll assume its a filename first.  Because: there
212
     are different ways of writing the same number, such as "3" -->
213
     "+3", "3.1" --> "3.10", so someone accidently using the file when
214
     they mean to use the number has easy ways of changing the number
215
     representation, since these trivial transformations will probably
216
     not all result in valid filenames. Another problem is that one
217
     really wants a general robust test to see if a given string is a
218
     valid number representation AND NOTHING BUT THAT, and sscanf() is
219
     not that test.  In any case, if there are to be improved smarts
220
     about this matter, they need to be implemented below and nowhere
221
     else. */
222
223
  nrrd = nrrdNew();
224
  ret = nrrdLoad(nrrd, str, NULL);
225
  if (!ret) {
226
    /* first attempt at nrrdLoad() was SUCCESSFUL */
227
    nrrdIterSetOwnNrrd(*iterP, nrrd);
228
  } else {
229
    /* so it didn't load as a nrrd- if its because fopen() failed,
230
       then we'll try it as a number.  If its for another reason,
231
       then we complain */
232
    nrrdNuke(nrrd);
233
    if (2 != ret) {
234
      /* it failed because of something besides the fopen(), so complain */
235
      nerr = biffGetDone(NRRD);
236
      airStrcpy(err, AIR_STRLEN_HUGE, nerr);
237
      airMopError(mop); return 1;
238
    } else {
239
      /* fopen() failed, so it probably wasn't meant to be a filename */
240
      free(biffGetDone(NRRD));
241
      ret = airSingleSscanf(str, "%lf", &val);
242
      if (_nrrdLooksLikeANumber(str)
243
          || (1 == ret && (!AIR_EXISTS(val)
244
                           || AIR_ABS(AIR_PI - val) < 0.0001
245
                           || AIR_ABS(-AIR_PI - val) < 0.0001))) {
246
        /* either it patently looks like a number, or,
247
           it already parsed as a number and it is a special value */
248
        if (1 == ret) {
249
          nrrdIterSetValue(*iterP, val);
250
        } else {
251
          /* oh, this is bad. */
252
          fprintf(stderr, "%s: PANIC, is it a number or not?", me);
253
          exit(1);
254
        }
255
      } else {
256
        /* it doesn't look like a number, but the fopen failed, so
257
           we'll let it fail again and pass back the error messages */
258
        if (nrrdLoad(nrrd = nrrdNew(), str, NULL)) {
259
          nerr = biffGetDone(NRRD);
260
          airStrcpy(err, AIR_STRLEN_HUGE, nerr);
261
          airMopError(mop); return 1;
262
        } else {
263
          /* what the hell? */
264
          fprintf(stderr, "%s: PANIC, is it a nrrd or not?", me);
265
          exit(1);
266
        }
267
      }
268
    }
269
  }
270
  airMopAdd(mop, iterP, (airMopper)airSetNull, airMopOnError);
271
  airMopOkay(mop);
272
  return 0;
273
}
274
275
hestCB
276
_nrrdHestIter = {
277
  sizeof(NrrdIter *),
278
  "nrrd/value",
279
  _nrrdHestIterParse,
280
  (airMopper)nrrdIterNix
281
};
282
283
hestCB *
284
nrrdHestIter = &_nrrdHestIter;