GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/nrrd/encodingBzip2.c Lines: 1 78 1.3 %
Date: 2017-05-26 Branches: 0 46 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
#if TEEM_BZIP2
28
#include <bzlib.h>
29
#endif
30
31
static int
32
_nrrdEncodingBzip2_available(void) {
33
34
#if TEEM_BZIP2
35
8
  return AIR_TRUE;
36
#else
37
  return AIR_FALSE;
38
#endif
39
}
40
41
static int
42
_nrrdEncodingBzip2_read(FILE *file, void *_data, size_t elNum,
43
                        Nrrd *nrrd, NrrdIoState *nio) {
44
  static const char me[]="_nrrdEncodingBzip2_read";
45
#if TEEM_BZIP2
46
  size_t bsize, total_read, block_size;
47
  int read, bzerror=BZ_OK;
48
  long int bi;
49
  char *data;
50
  BZFILE* bzfin;
51
52
  bsize = nrrdElementSize(nrrd)*elNum;
53
54
  /* Create the BZFILE* for reading in the gzipped data. */
55
  bzfin = BZ2_bzReadOpen(&bzerror, file, 0, 0, NULL, 0);
56
  if (bzerror != BZ_OK) {
57
    /* there was a problem */
58
    biffAddf(NRRD, "%s: error opening BZFILE: %s", me,
59
             BZ2_bzerror(bzfin, &bzerror));
60
    BZ2_bzReadClose(&bzerror, bzfin);
61
    return 1;
62
  }
63
64
  /* Here is where we do the byte skipping. */
65
  for(bi=0; bi<nio->byteSkip; bi++) {
66
    unsigned char b;
67
    /* Check to see if a single byte was able to be read. */
68
    read = BZ2_bzRead(&bzerror, bzfin, &b, 1);
69
    if (read != 1 || bzerror != BZ_OK) {
70
      biffAddf(NRRD, "%s: hit an error skipping byte %ld of %ld: %s",
71
               me, bi, nio->byteSkip, BZ2_bzerror(bzfin, &bzerror));
72
      return 1;
73
    }
74
  }
75
76
  /* bzip2 can handle data sizes up to INT_MAX, so we can't just
77
     pass in the bsize, because it might be too large for an int.
78
     Therefore it must be read in chunks if the size is larger
79
     than INT_MAX. */
80
  if (bsize <= INT_MAX) {
81
    block_size = bsize;
82
  } else {
83
    block_size = INT_MAX;
84
  }
85
86
  /* This counter will help us to make sure that we read as much data
87
     as we think we should. */
88
  total_read = 0;
89
  /* Pointer to the blocks as we read them. */
90
  data = (char *)_data;
91
92
  /* Ok, now we can begin reading. */
93
  bzerror = BZ_OK;
94
  while ((read = BZ2_bzRead(&bzerror, bzfin, data, block_size))
95
          && (BZ_OK == bzerror || BZ_STREAM_END == bzerror) ) {
96
    /* Increment the data pointer to the next available spot. */
97
    data += read;
98
    total_read += read;
99
    /* We only want to read as much data as we need, so we need to check
100
       to make sure that we don't request data that might be there but that
101
       we don't want.  This will reduce block_size when we get to the last
102
       block (which may be smaller than block_size).
103
    */
104
    if (bsize >= total_read
105
        && bsize - total_read < block_size)
106
      block_size = bsize - total_read;
107
  }
108
109
  if (!( BZ_OK == bzerror || BZ_STREAM_END == bzerror )) {
110
    biffAddf(NRRD, "%s: error reading from BZFILE: %s",
111
             me, BZ2_bzerror(bzfin, &bzerror));
112
    return 1;
113
  }
114
115
  /* Close the BZFILE. */
116
  BZ2_bzReadClose(&bzerror, bzfin);
117
  if (BZ_OK != bzerror) {
118
    biffAddf(NRRD, "%s: error closing BZFILE: %s", me,
119
             BZ2_bzerror(bzfin, &bzerror));
120
    return 1;
121
  }
122
123
  /* Check to see if we got out as much as we thought we should. */
124
  if (total_read != bsize) {
125
    char stmp1[AIR_STRLEN_SMALL], stmp2[AIR_STRLEN_SMALL];
126
    biffAddf(NRRD, "%s: expected %s bytes but received %s", me,
127
             airSprintSize_t(stmp1, bsize),
128
             airSprintSize_t(stmp2, total_read));
129
    return 1;
130
  }
131
132
  return 0;
133
#else
134
  AIR_UNUSED(file);
135
  AIR_UNUSED(_data);
136
  AIR_UNUSED(elNum);
137
  AIR_UNUSED(nrrd);
138
  AIR_UNUSED(nio);
139
  biffAddf(NRRD, "%s: sorry, this nrrd not compiled with bzip2 enabled", me);
140
  return 1;
141
#endif
142
}
143
144
static int
145
_nrrdEncodingBzip2_write(FILE *file, const void *_data, size_t elNum,
146
                         const Nrrd *nrrd, NrrdIoState *nio) {
147
  static const char me[]="_nrrdEncodingBzip2_write";
148
#if TEEM_BZIP2
149
  size_t bsize, total_written, block_size;
150
  int bs, bzerror=BZ_OK;
151
  char *data;
152
  BZFILE* bzfout;
153
154
  bsize = nrrdElementSize(nrrd)*elNum;
155
156
  /* Set compression block size. */
157
  if (1 <= nio->bzip2BlockSize && nio->bzip2BlockSize <= 9) {
158
    bs = nio->bzip2BlockSize;
159
  } else {
160
    bs = 9;
161
  }
162
  /* Open bzfile for writing. Verbosity and work factor are set
163
     to default values. */
164
  bzfout = BZ2_bzWriteOpen(&bzerror, file, bs, 0, 0);
165
  if (BZ_OK != bzerror) {
166
    biffAddf(NRRD, "%s: error opening BZFILE: %s", me,
167
             BZ2_bzerror(bzfout, &bzerror));
168
    BZ2_bzWriteClose(&bzerror, bzfout, 0, NULL, NULL);
169
    return 1;
170
  }
171
172
  /* bzip2 can handle data sizes up to INT_MAX, so we can't just
173
     pass in the bsize, because it might be too large for an int.
174
     Therefore it must be read in chunks if the bsize is larger
175
     than INT_MAX. */
176
  if (bsize <= INT_MAX) {
177
    block_size = bsize;
178
  } else {
179
    block_size = INT_MAX;
180
  }
181
182
  /* This counter will help us to make sure that we write as much data
183
     as we think we should. */
184
  total_written = 0;
185
  /* Pointer to the blocks as we write them. */
186
  data = (char *)_data;
187
188
  /* Ok, now we can begin writing. */
189
  bzerror = BZ_OK;
190
  while (bsize - total_written > block_size) {
191
    BZ2_bzWrite(&bzerror, bzfout, data, block_size);
192
    if (BZ_OK != bzerror) break;
193
    /* Increment the data pointer to the next available spot. */
194
    data += block_size;
195
    total_written += block_size;
196
  }
197
  /* write the last (possibly smaller) block when its humungous data;
198
     write the whole data when its small */
199
  if (BZ_OK == bzerror) {
200
    block_size = bsize >= total_written ? bsize - total_written : 0;
201
    BZ2_bzWrite(&bzerror, bzfout, data, block_size);
202
    total_written += block_size;
203
  }
204
205
  if (BZ_OK != bzerror) {
206
    biffAddf(NRRD, "%s: error writing to BZFILE: %s",
207
             me, BZ2_bzerror(bzfout, &bzerror));
208
    return 1;
209
  }
210
211
  /* Close the BZFILE. */
212
  BZ2_bzWriteClose(&bzerror, bzfout, 0, NULL, NULL);
213
  if (BZ_OK != bzerror) {
214
    biffAddf(NRRD, "%s: error closing BZFILE: %s", me,
215
             BZ2_bzerror(bzfout, &bzerror));
216
    return 1;
217
  }
218
219
  /* Check to see if we got out as much as we thought we should. */
220
  if (total_written != bsize) {
221
    char stmp1[AIR_STRLEN_SMALL], stmp2[AIR_STRLEN_SMALL];
222
    biffAddf(NRRD, "%s: expected to write %s bytes, but only wrote %s", me,
223
             airSprintSize_t(stmp1, bsize),
224
             airSprintSize_t(stmp2, total_written));
225
    return 1;
226
  }
227
228
  return 0;
229
#else
230
  AIR_UNUSED(file);
231
  AIR_UNUSED(_data);
232
  AIR_UNUSED(elNum);
233
  AIR_UNUSED(nrrd);
234
  AIR_UNUSED(nio);
235
  biffAddf(NRRD, "%s: sorry, this nrrd not compiled with bzip2 enabled", me);
236
  return 1;
237
#endif
238
}
239
240
const NrrdEncoding
241
_nrrdEncodingBzip2 = {
242
  "bzip2",      /* name */
243
  "raw.bz2",   /* suffix */
244
  AIR_TRUE,    /* endianMatters */
245
  AIR_TRUE,   /* isCompression */
246
  _nrrdEncodingBzip2_available,
247
  _nrrdEncodingBzip2_read,
248
  _nrrdEncodingBzip2_write
249
};
250
251
const NrrdEncoding *const
252
nrrdEncodingBzip2 = &_nrrdEncodingBzip2;