~ubuntu-branches/ubuntu/quantal/pytables/quantal

« back to all changes in this revision

Viewing changes to src/H5Zbzip2.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Dröge
  • Date: 2005-11-27 20:25:34 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20051127202534-l8jzyd8357krw40h
Tags: 1.1.1-1ubuntu1
* Sync with Debian:
  + Use python 2.4 as default

Show diffs side-by-side

added added

removed removed

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