~ubuntu-branches/ubuntu/natty/pytables/natty-updates

« back to all changes in this revision

Viewing changes to src/H5Zbzip2.c

  • Committer: Bazaar Package Importer
  • Author(s): Alexandre Fayolle
  • Date: 2006-06-28 10:45:03 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 5.
  • Revision ID: james.westby@ubuntu.com-20060628104503-cc251q5o5j3e2k10
  * Fixed call to pyversions in debian/rules which failed on recent versions 
    of pyversions
  * Fixed clean rule in debian/rules which left the stamp files behind
  * Acknowledge NMU
  * Added Alexandre Fayolle to uploaders

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "H5Zbzip2.h"
 
2
 
 
3
#include <sys/types.h>
 
4
#include <stdlib.h>
 
5
#include <string.h>
 
6
#include <assert.h>
 
7
#include <stdio.h>
 
8
#include <hdf5.h>
 
9
 
 
10
 
 
11
#ifdef HAVE_BZ2_LIB
 
12
#include "bzlib.h"
 
13
#endif  /* defined HAVE_BZ2_LIB */
 
14
 
 
15
size_t bzip2_deflate(unsigned int flags, size_t cd_nelmts,
 
16
                     const unsigned int cd_values[], size_t nbytes,
 
17
                     size_t *buf_size, void **buf);
 
18
 
 
19
 
 
20
int register_bzip2(char **version, char **date)
 
21
{
 
22
#ifdef HAVE_BZ2_LIB
 
23
  char *libver, *versionp, *datep, *sep;
 
24
 
 
25
#if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 7
 
26
   /* 1.6.x */
 
27
  H5Z_class_t filter_class = {
 
28
    (H5Z_filter_t)(FILTER_BZIP2),  /* filter_id */
 
29
    "bzip2",                       /* comment */
 
30
    NULL,                          /* can_apply_func */
 
31
    NULL,                          /* set_local_func */
 
32
    (H5Z_func_t)(bzip2_deflate)    /* filter_func */
 
33
  };
 
34
#else
 
35
   /* 1.7.x */
 
36
  H5Z_class_t filter_class = {
 
37
    H5Z_CLASS_T_VERS,             /* H5Z_class_t version */
 
38
    (H5Z_filter_t)(FILTER_BZIP2), /* filter_id */
 
39
    1, 1,                         /* Encoding and decoding enabled */
 
40
    "bzip2",                      /* comment */
 
41
    NULL,                         /* can_apply_func */
 
42
    NULL,                         /* set_local_func */
 
43
    (H5Z_func_t)(bzip2_deflate)   /* filter_func */
 
44
};
 
45
#endif /* if H5_VERSION < "1.7" */
 
46
 
 
47
  /* Register the filter class for the bzip2 compressor. */
 
48
  H5Zregister(&filter_class);
 
49
 
 
50
  /* Get the library major version from the version string. */
 
51
  libver = strdup(BZ2_bzlibVersion());
 
52
  sep = strchr(libver, ',');
 
53
  assert(sep != NULL);
 
54
  assert(*(sep + 1) == ' ');
 
55
  *sep = '\0';
 
56
  versionp = libver;
 
57
  datep = sep + 2;  /* after the comma and a space */
 
58
 
 
59
  *version = strdup(versionp);
 
60
  *date = strdup(datep);
 
61
 
 
62
  free(libver);
 
63
  return 1;  /* library is available */
 
64
 
 
65
#else
 
66
  return 0;  /* library is not available */
 
67
#endif  /* defined HAVE_BZ2_LIB */
 
68
 
 
69
}
 
70
 
 
71
 
 
72
size_t bzip2_deflate(unsigned int flags, size_t cd_nelmts,
 
73
                     const unsigned int cd_values[], size_t nbytes,
 
74
                     size_t *buf_size, void **buf)
 
75
{
 
76
#ifdef HAVE_BZ2_LIB
 
77
  char *outbuf = NULL;
 
78
  size_t outbuflen, outdatalen;
 
79
  int ret;
 
80
 
 
81
  if (flags & H5Z_FLAG_REVERSE) {
 
82
 
 
83
    /** Decompress data.
 
84
     **
 
85
     ** This process is troublesome since the size of uncompressed data
 
86
     ** is unknown, so the low-level interface must be used.
 
87
     ** Data is decompressed to the output buffer (which is sized
 
88
     ** for the average case); if it gets full, its size is doubled
 
89
     ** and decompression continues.  This avoids repeatedly trying to
 
90
     ** decompress the whole block, which could be really inefficient.
 
91
     **/
 
92
 
 
93
    bz_stream stream;
 
94
    char *newbuf = NULL;
 
95
    size_t newbuflen;
 
96
 
 
97
    /* Prepare the output buffer. */
 
98
    outbuflen = nbytes * 3 + 1;  /* average bzip2 compression ratio is 3:1 */
 
99
    outbuf = malloc(outbuflen);
 
100
    if (outbuf == NULL) {
 
101
      fprintf(stderr, "memory allocation failed for bzip2 decompression\n");
 
102
      goto cleanupAndFail;
 
103
    }
 
104
 
 
105
    /* Use standard malloc()/free() for internal memory handling. */
 
106
    stream.bzalloc = NULL;
 
107
    stream.bzfree = NULL;
 
108
    stream.opaque = NULL;
 
109
 
 
110
    /* Start decompression. */
 
111
    ret = BZ2_bzDecompressInit(&stream, 0, 0);
 
112
    if (ret != BZ_OK) {
 
113
      fprintf(stderr, "bzip2 decompression start failed with error %d\n", ret);
 
114
      goto cleanupAndFail;
 
115
    }
 
116
 
 
117
    /* Feed data to the decompression process and get decompressed data. */
 
118
    stream.next_out = outbuf;
 
119
    stream.avail_out = outbuflen;
 
120
    stream.next_in = *buf;
 
121
    stream.avail_in = nbytes;
 
122
    do {
 
123
      ret = BZ2_bzDecompress(&stream);
 
124
      if (ret < 0) {
 
125
        fprintf(stderr, "BUG: bzip2 decompression failed with error %d\n", ret);
 
126
        goto cleanupAndFail;
 
127
      }
 
128
 
 
129
      if (ret != BZ_STREAM_END && stream.avail_out == 0) {
 
130
        /* Grow the output buffer. */
 
131
        newbuflen = outbuflen * 2;
 
132
        newbuf = realloc(outbuf, newbuflen);
 
133
        if (newbuf == NULL) {
 
134
          fprintf(stderr, "memory allocation failed for bzip2 decompression\n");
 
135
          goto cleanupAndFail;
 
136
        }
 
137
        stream.next_out = newbuf + outbuflen;  /* half the new buffer behind */
 
138
        stream.avail_out = outbuflen;  /* half the new buffer ahead */
 
139
        outbuf = newbuf;
 
140
        outbuflen = newbuflen;
 
141
      }
 
142
    } while (ret != BZ_STREAM_END);
 
143
 
 
144
    /* End compression. */
 
145
    outdatalen = stream.total_out_lo32;
 
146
    ret = BZ2_bzDecompressEnd(&stream);
 
147
    if (ret != BZ_OK) {
 
148
      fprintf(stderr, "bzip2 compression end failed with error %d\n", ret);
 
149
      goto cleanupAndFail;
 
150
    }
 
151
 
 
152
  } else {
 
153
 
 
154
    /** Compress data.
 
155
     **
 
156
     ** This is quite simple, since the size of compressed data in the worst
 
157
     ** case is known and it is not much bigger than the size of uncompressed
 
158
     ** data.  This allows us to use the simplified one-shot interface to
 
159
     ** compression.
 
160
     **/
 
161
 
 
162
    int blockSize100k = 9;
 
163
 
 
164
    /* Get compression block size if present. */
 
165
    if (cd_nelmts > 0) {
 
166
      blockSize100k = cd_values[0];
 
167
      if (blockSize100k < 1 || blockSize100k > 9) {
 
168
        fprintf(stderr, "invalid compression block size: %d\n", blockSize100k);
 
169
        goto cleanupAndFail;
 
170
      }
 
171
    }
 
172
 
 
173
    /* Prepare the output buffer. */
 
174
    outbuflen = nbytes + nbytes / 100 + 600;  /* worst case (bzip2 docs) */
 
175
    outbuf = malloc(outbuflen);
 
176
    if (outbuf == NULL) {
 
177
      fprintf(stderr, "memory allocation failed for bzip2 compression\n");
 
178
      goto cleanupAndFail;
 
179
    }
 
180
 
 
181
    /* Compress data. */
 
182
    outdatalen = outbuflen;
 
183
    ret = BZ2_bzBuffToBuffCompress(outbuf, &outdatalen, *buf, nbytes,
 
184
                                   blockSize100k, 0, 0);
 
185
    if (ret != BZ_OK) {
 
186
      fprintf(stderr, "bzip2 compression failed with error %d\n", ret);
 
187
      goto cleanupAndFail;
 
188
    }
 
189
  }
 
190
 
 
191
  /* Always replace the input buffer with the output buffer. */
 
192
  free(*buf);
 
193
  *buf = outbuf;
 
194
  *buf_size = outbuflen;
 
195
  return outdatalen;
 
196
 
 
197
 cleanupAndFail:
 
198
  if (outbuf)
 
199
    free(outbuf);
 
200
  return 0;
 
201
#else
 
202
  return 0;
 
203
#endif  /* defined HAVE_BZ2_LIB */
 
204
}