GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/nrrd/encodingAscii.c Lines: 1 64 1.6 %
Date: 2017-05-26 Branches: 0 35 0.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 "nrrd.h"
25
#include "privateNrrd.h"
26
27
static FILE *_fileSave = NULL;
28
29
static int
30
_nrrdEncodingAscii_available(void) {
31
32
4
  return AIR_TRUE;
33
}
34
35
static int
36
_nrrdEncodingAscii_read(FILE *file, void *_data, size_t elNum,
37
                        Nrrd *nrrd, NrrdIoState *nio) {
38
  static const char me[]="_nrrdEncodingAscii_read";
39
  char numbStr[AIR_STRLEN_HUGE];  /* HEY: fix this */
40
  char *nstr;
41
  size_t I;
42
  char *data;
43
  int tmp;
44
45
  AIR_UNUSED(nio);
46
  _fileSave = file;
47
  if (nrrdTypeBlock == nrrd->type) {
48
    biffAddf(NRRD, "%s: can't read nrrd type %s from %s", me,
49
             airEnumStr(nrrdType, nrrdTypeBlock),
50
             nrrdEncodingAscii->name);
51
    return 1;
52
  }
53
  data = (char*)_data;
54
  I = 0;
55
  while (I < elNum) {
56
    char stmp1[AIR_STRLEN_SMALL], stmp2[AIR_STRLEN_SMALL];
57
    /* HEY: we can easily suffer here from a standard buffer overflow problem;
58
       this was a source of a mysterious unu crash:
59
         echo "0 0 0 0 1 0 0 0 0" \
60
          | unu reshape -s 9 1 1 \
61
          | unu pad -min 0 0 0 -max 8 8 8 \
62
          | unu make -s 9 9 9 -t float -e ascii -ls 9 \
63
            -spc LPS -orig "(0,0,0)" -dirs "(1,0,0) (0,1,0) (0,0,1)"
64
       This particular case is resolved by changing AIR_STRLEN_HUGE
65
       to AIR_STRLEN_HUGE*100, but the general problem remains.  This
66
       motivated adding the memory corruption test */
67
    if (1 != fscanf(file, "%s", numbStr)) {
68
      biffAddf(NRRD, "%s: couldn't parse element %s of %s", me,
69
               airSprintSize_t(stmp1, I+1),
70
               airSprintSize_t(stmp2, elNum));
71
      return 1;
72
    }
73
    if (file != _fileSave) {
74
      fprintf(stderr, "%s: PANIC memory corruption detected\n", me);
75
      /* this may crash, hence the fprintf above to help debug */
76
      biffAddf(NRRD, "%s: PANIC memory corruption detected", me);
77
      return 1;
78
    }
79
    if (!strcmp(",", numbStr)) {
80
      /* its an isolated comma, not a value, pass over this */
81
      continue;
82
    }
83
    /* get past any commas prefixing a number (without space) */
84
    nstr = numbStr + strspn(numbStr, ",");
85
    if (nrrd->type >= nrrdTypeInt) {
86
      /* sscanf supports putting value directly into this type */
87
      if (1 != airSingleSscanf(nstr, nrrdTypePrintfStr[nrrd->type],
88
                               (void*)(data + I*nrrdElementSize(nrrd)))) {
89
        biffAddf(NRRD, "%s: couldn't parse %s %s of %s (\"%s\")", me,
90
                 airEnumStr(nrrdType, nrrd->type),
91
                 airSprintSize_t(stmp1, I+1),
92
                 airSprintSize_t(stmp2, elNum), nstr);
93
        return 1;
94
      }
95
    } else {
96
      /* sscanf value into an int first */
97
      if (1 != airSingleSscanf(nstr, "%d", &tmp)) {
98
        biffAddf(NRRD, "%s: couldn't parse element %s of %s (\"%s\")", me,
99
                 airSprintSize_t(stmp1, I+1),
100
                 airSprintSize_t(stmp2, elNum), nstr);
101
        return 1;
102
      }
103
      nrrdIInsert[nrrd->type](data, I, tmp);
104
    }
105
    I++;
106
  }
107
108
  return 0;
109
}
110
111
static int
112
_nrrdEncodingAscii_write(FILE *file, const void *_data, size_t elNum,
113
                         const Nrrd *nrrd, NrrdIoState *nio) {
114
  static const char me[]="_nrrdEncodingAscii_write";
115
  char buff[AIR_STRLEN_MED];
116
  size_t bufflen, linelen;
117
  const char *data;
118
  size_t I;
119
  int newlined;
120
121
  if (nrrdTypeBlock == nrrd->type) {
122
    biffAddf(NRRD, "%s: can't write nrrd type %s to %s", me,
123
             airEnumStr(nrrdType, nrrdTypeBlock),
124
             nrrdEncodingAscii->name);
125
    return 1;
126
  }
127
  data = AIR_CAST(const char*, _data);
128
  linelen = 0;
129
  for (I=0; I<elNum; I++) {
130
    nrrdSprint[nrrd->type](buff, data);
131
    if (1 == nrrd->dim) {
132
      fprintf(file, "%s\n", buff);
133
      newlined = AIR_TRUE;
134
    } else if (nrrd->dim == 2
135
               && nrrd->axis[0].size <= nio->valsPerLine) {
136
      int nonewline = (I+1)%(nrrd->axis[0].size);
137
      fprintf(file, "%s%c", buff, nonewline ? ' ' : '\n');
138
      newlined = !nonewline;
139
    } else {
140
      bufflen = strlen(buff);
141
      if (linelen+bufflen+1 <= nio->charsPerLine) {
142
        fprintf(file, "%s%s", I ? " " : "", buff);
143
        linelen += (I ? 1 : 0) + bufflen;
144
      } else {
145
        fprintf(file, "\n%s", buff);
146
        linelen = bufflen;
147
      }
148
      newlined = AIR_FALSE;
149
    }
150
    data += nrrdElementSize(nrrd);
151
  }
152
  if (!newlined) {
153
    /* always end file with a carraige return; but guard with this
154
       conditional so we don't create a final blank line */
155
    fprintf(file, "\n");
156
  }
157
  fflush(file);
158
159
  return 0;
160
}
161
162
const NrrdEncoding
163
_nrrdEncodingAscii = {
164
  "ASCII",      /* name */
165
  "ascii",      /* suffix */
166
  AIR_FALSE,   /* endianMatters */
167
  AIR_FALSE,   /* isCompression */
168
  _nrrdEncodingAscii_available,
169
  _nrrdEncodingAscii_read,
170
  _nrrdEncodingAscii_write
171
};
172
173
const NrrdEncoding *const
174
nrrdEncodingAscii = &_nrrdEncodingAscii;