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; |