GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/nrrd/encodingRaw.c Lines: 52 89 58.4 %
Date: 2017-05-26 Branches: 22 52 42.3 %

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 int
28
_nrrdEncodingRaw_available(void) {
29
30
52
  return AIR_TRUE;
31
}
32
33
static int
34
_nrrdEncodingRaw_read(FILE *file, void *data, size_t elementNum,
35
                      Nrrd *nrrd, NrrdIoState *nio) {
36
  static const char me[]="_nrrdEncodingRaw_read";
37
  size_t ret, bsize;
38
  int fd, dio, car;
39
  long savePos;
40
  char *data_c;
41
  size_t elementSize, maxChunkSize, remainderValue, chunkSize;
42
  size_t retTmp;
43
50
  char stmp[3][AIR_STRLEN_SMALL];
44
45
25
  bsize = nrrdElementSize(nrrd)*elementNum;
46
25
  if (nio->format->usesDIO) {
47
23
    fd = fileno(file);
48
23
    dio = airDioTest(fd, data, bsize);
49
23
  } else {
50
    fd = -1;
51
    dio = airNoDio_format;
52
  }
53

50
  if (airNoDio_okay == dio) {
54
25
    if (2 <= nrrdStateVerboseIO) {
55
      fprintf(stderr, "with direct I/O ... ");
56
    }
57
    ret = airDioRead(fd, data, bsize);
58
    if (ret != bsize) {
59
      biffAddf(NRRD, "%s: airDioRead got read only %s of %sbytes "
60
               "(%g%% of expected)", me,
61
               airSprintSize_t(stmp[0], ret),
62
               airSprintSize_t(stmp[1], bsize),
63
               100.0*AIR_CAST(double, ret)/AIR_CAST(double, bsize));
64
      return 1;
65
    }
66
  } else {
67
25
    if (2 <= nrrdStateVerboseIO) {
68
25
      if (AIR_DIO && nio->format->usesDIO) {
69
        fprintf(stderr, "with fread(), not DIO: %s ...", airNoDioErr(dio));
70
      }
71
    }
72
73
    /* HEY: There's a bug in fread/fwrite in gcc 4.2.1 (with SnowLeopard).
74
            When it reads/writes a >=2GB data array, it pretends to succeed
75
            (i.e. the return value is the right number) but it hasn't
76
            actually read/written the data.  The work-around is to loop
77
            over the data, reading/writing 1GB (or smaller) chunks.         */
78
    ret = 0;
79
    data_c = (char *)data;
80
25
    elementSize = nrrdElementSize(nrrd);
81
25
    maxChunkSize = 1024 * 1024 * 1024 / elementSize;
82
75
    while(ret < elementNum) {
83
25
      remainderValue = elementNum-ret;
84
25
      if (remainderValue < maxChunkSize) {
85
        chunkSize = remainderValue;
86
25
      } else {
87
        chunkSize = maxChunkSize;
88
      }
89
      retTmp =
90
25
        fread(&(data_c[ret*elementSize]), elementSize, chunkSize, file);
91
25
      ret += retTmp;
92
25
      if (retTmp != chunkSize) {
93
        biffAddf(NRRD, "%s: fread got only %s %s-sized things, not %s "
94
                 "(%g%% of expected)", me,
95
                 airSprintSize_t(stmp[0], ret),
96
                 airSprintSize_t(stmp[1], nrrdElementSize(nrrd)),
97
                 airSprintSize_t(stmp[2], elementNum),
98
                 100.0*AIR_CAST(double, ret)/AIR_CAST(double, elementNum));
99
        return 1;
100
      }
101
    }
102
103
25
    car = fgetc(file);
104
25
    if (EOF != car) {
105
4
      if (1 <= nrrdStateVerboseIO) {
106
4
        fprintf(stderr, "%s: WARNING: finished reading raw data, "
107
                "but file not at EOF\n", me);
108
4
      }
109
4
      ungetc(car, file);
110
4
    }
111

25
    if (2 <= nrrdStateVerboseIO && nio->byteSkip && stdin != file) {
112
      savePos = ftell(file);
113
      if (!fseek(file, 0, SEEK_END)) {
114
        double frac = (AIR_CAST(double, bsize)
115
                       /AIR_CAST(double, ftell(file) + 1));
116
        fprintf(stderr, "(%s: used %g%% of file for nrrd data)\n", me,
117
                100.0*frac);
118
        fseek(file, savePos, SEEK_SET);
119
      }
120
    }
121
  }
122
123
25
  return 0;
124
25
}
125
126
static int
127
_nrrdEncodingRaw_write(FILE *file, const void *data, size_t elementNum,
128
                       const Nrrd *nrrd, NrrdIoState *nio) {
129
  static const char me[]="_nrrdEncodingRaw_write";
130
  int fd, dio;
131
  size_t ret, bsize;
132
  const char *data_c;
133
  size_t elementSize, maxChunkSize, remainderValue, chunkSize;
134
  size_t retTmp;
135
24
  char stmp[3][AIR_STRLEN_SMALL];
136
137
12
  bsize = nrrdElementSize(nrrd)*elementNum;
138
12
  if (nio->format->usesDIO) {
139
11
    fd = fileno(file);
140
11
    dio = airDioTest(fd, data, bsize);
141
11
  } else {
142
    fd = -1;
143
    dio = airNoDio_format;
144
  }
145

24
  if (airNoDio_okay == dio) {
146
12
    if (2 <= nrrdStateVerboseIO) {
147
      fprintf(stderr, "with direct I/O ... ");
148
    }
149
    ret = airDioWrite(fd, data, bsize);
150
    if (ret != bsize) {
151
      biffAddf(NRRD, "%s: airDioWrite wrote only %s of %s bytes "
152
               "(%g%% of expected)", me,
153
               airSprintSize_t(stmp[0], ret),
154
               airSprintSize_t(stmp[1], bsize),
155
               100.0*AIR_CAST(double, ret)/AIR_CAST(double, bsize));
156
      return 1;
157
    }
158
  } else {
159
12
    if (2 <= nrrdStateVerboseIO) {
160
12
      if (AIR_DIO && nio->format->usesDIO) {
161
        fprintf(stderr, "with fread(), not DIO: %s ...", airNoDioErr(dio));
162
      }
163
    }
164
165
    /* HEY: There's a bug in fread/fwrite in gcc 4.2.1 (with SnowLeopard).
166
            When it reads/writes a >=2GB data array, it pretends to succeed
167
            (i.e. the return value is the right number) but it hasn't
168
            actually read/written the data.  The work-around is to loop
169
            over the data, reading/writing 1GB (or smaller) chunks.         */
170
    ret = 0;
171
    data_c = AIR_CAST(const char *, data);
172
12
    elementSize = nrrdElementSize(nrrd);
173
12
    maxChunkSize = 1024 * 1024 * 1024 / elementSize;
174
36
    while(ret < elementNum) {
175
12
      remainderValue = elementNum-ret;
176
12
      if (remainderValue < maxChunkSize) {
177
        chunkSize = remainderValue;
178
12
      } else {
179
        chunkSize = maxChunkSize;
180
      }
181
      retTmp =
182
12
        fwrite(&(data_c[ret*elementSize]), elementSize, chunkSize, file);
183
12
      ret += retTmp;
184
12
      if (retTmp != chunkSize) {
185
        biffAddf(NRRD, "%s: fwrite wrote only %s %s-sized things, not %s "
186
                 "(%g%% of expected)", me,
187
                 airSprintSize_t(stmp[0], ret),
188
                 airSprintSize_t(stmp[1], nrrdElementSize(nrrd)),
189
                 airSprintSize_t(stmp[2], elementNum),
190
                 100.0*AIR_CAST(double, ret)/AIR_CAST(double, elementNum));
191
        return 1;
192
      }
193
    }
194
195
12
    fflush(file);
196
    /*
197
    if (ferror(file)) {
198
      biffAddf(NRRD, "%s: ferror returned non-zero", me);
199
      return 1;
200
    }
201
    */
202
  }
203
12
  return 0;
204
12
}
205
206
const NrrdEncoding
207
_nrrdEncodingRaw = {
208
  "raw",      /* name */
209
  "raw",      /* suffix */
210
  AIR_TRUE,   /* endianMatters */
211
  AIR_FALSE,  /* isCompression */
212
  _nrrdEncodingRaw_available,
213
  _nrrdEncodingRaw_read,
214
  _nrrdEncodingRaw_write
215
};
216
217
const NrrdEncoding *const
218
nrrdEncodingRaw = &_nrrdEncodingRaw;