2 This library is free software; you can redistribute it and/or
3 modify it under the terms of the GNU Library General Public
4 License as published by the Free Software Foundation; either
5 version 2 of the License, or (at your option) any later version.
7 This library is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 Library General Public License for more details.
12 You should have received a copy of the GNU Library General Public
13 License along with this library; if not, write to the
14 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
15 Boston, MA 02110-1301, USA.
18 #include "../../../config/config.h"
24 #include <caml/mlvalues.h>
25 #include <caml/alloc.h>
26 #include <caml/callback.h>
27 #include <caml/fail.h>
28 #include <caml/memory.h>
30 /* Bzip2 interface code */
32 #define BZStream_val(v) ((bz_stream *) (v))
34 static const value
* camlzip_bzerror_exn
= NULL
;
37 static void camlzip_bzerror(char * fn
, int err
)
40 value s1
= Val_unit
, s2
= Val_unit
, bucket
= Val_unit
;
42 if (camlzip_bzerror_exn
== NULL
) {
43 camlzip_bzerror_exn
= caml_named_value("Bzlib.Error");
44 if (camlzip_bzerror_exn
== NULL
)
45 invalid_argument("Exception Bzlib.Error not initialized");
47 Begin_roots3(s1
, s2
, bucket
);
53 case BZ_SEQUENCE_ERROR
:
65 case BZ_DATA_ERROR_MAGIC
:
71 bucket
= alloc_small(3, 0);
72 Field(bucket
, 0) = *camlzip_bzerror_exn
;
73 Field(bucket
, 1) = s1
;
74 Field(bucket
, 2) = s2
;
79 static value
camlzip_new_bzstream(void)
81 bz_stream
* bzs
= (bz_stream
*) malloc(sizeof(bz_stream
));
90 int camlzip_action_table
[] = { BZ_RUN
, BZ_FLUSH
, BZ_FINISH
};
94 value
camlzip_bzCompressInit(value blockSize100k
, value verbosity
, value workFactor
) {
97 value vbzs
= camlzip_new_bzstream();
98 if ((err
= BZ2_bzCompressInit(BZStream_val(vbzs
),
99 Int_val(blockSize100k
),
101 Int_val(workFactor
))) != BZ_OK
)
102 camlzip_bzerror("Zlib.deflateInit", err
);
105 failwith("Bzip2 compression not supported.");
109 value
camlzip_bzCompress(value vzs
, value srcbuf
, value srcpos
, value srclen
,
110 value dstbuf
, value dstpos
, value dstlen
,
114 bz_stream
* zs
= BZStream_val(vzs
);
116 long used_in
, used_out
;
119 zs
->next_in
= &Byte(srcbuf
, Long_val(srcpos
));
120 zs
->avail_in
= Long_val(srclen
);
121 zs
->next_out
= &Byte(dstbuf
, Long_val(dstpos
));
122 zs
->avail_out
= Long_val(dstlen
);
123 retcode
= BZ2_bzCompress(zs
, camlzip_action_table
[Int_val(vflush
)]);
124 if (retcode
< 0) camlzip_bzerror("Bzlib.compress", retcode
);
125 used_in
= Long_val(srclen
) - zs
->avail_in
;
126 used_out
= Long_val(dstlen
) - zs
->avail_out
;
127 zs
->next_in
= NULL
; /* not required, but cleaner */
128 zs
->next_out
= NULL
; /* (avoid dangling pointers into Caml heap) */
129 res
= alloc_small(3, 0);
130 Field(res
, 0) = Val_bool(retcode
== BZ_STREAM_END
);
131 Field(res
, 1) = Val_int(used_in
);
132 Field(res
, 2) = Val_int(used_out
);
135 failwith("Bzip2 compression not supported");
139 value
camlzip_bzCompress_bytecode(value
* arg
, int nargs
)
141 return camlzip_bzCompress(arg
[0], arg
[1], arg
[2], arg
[3],
142 arg
[4], arg
[5], arg
[6], arg
[7]);
145 value
camlzip_bzCompressEnd(value stream
) {
148 if ((err
= BZ2_bzCompressEnd(BZStream_val(stream
))) != BZ_OK
)
149 camlzip_bzerror("Bzlib.compress_end", err
);
150 free(BZStream_val(stream
));
152 failwith("Bzip2 compression not supported");
157 value
camlzip_bzDecompressInit(value verbosity
, value small
)
161 value vzs
= camlzip_new_bzstream();
162 if ((err
= BZ2_bzDecompressInit(BZStream_val(vzs
), Int_val(verbosity
), Bool_val(small
))) != BZ_OK
)
163 camlzip_bzerror("Bzlib.decompress_init", err
);
166 failwith("Bzip2 compression not supported");
170 value
camlzip_bzDecompress(value vzs
, value srcbuf
, value srcpos
, value srclen
,
171 value dstbuf
, value dstpos
, value dstlen
)
174 bz_stream
* zs
= BZStream_val(vzs
);
176 long used_in
, used_out
;
179 zs
->next_in
= &Byte(srcbuf
, Long_val(srcpos
));
180 zs
->avail_in
= Long_val(srclen
);
181 zs
->next_out
= &Byte(dstbuf
, Long_val(dstpos
));
182 zs
->avail_out
= Long_val(dstlen
);
183 retcode
= BZ2_bzDecompress(zs
);
185 camlzip_bzerror("Bzlib.decompress", retcode
);
186 used_in
= Long_val(srclen
) - zs
->avail_in
;
187 used_out
= Long_val(dstlen
) - zs
->avail_out
;
188 zs
->next_in
= NULL
; /* not required, but cleaner */
189 zs
->next_out
= NULL
; /* (avoid dangling pointers into Caml heap) */
190 res
= alloc_small(3, 0);
191 Field(res
, 0) = Val_bool(retcode
== BZ_STREAM_END
);
192 Field(res
, 1) = Val_int(used_in
);
193 Field(res
, 2) = Val_int(used_out
);
196 failwith("Bzip2 compression not supported");
200 value
camlzip_bzDecompress_bytecode(value
* arg
, int nargs
)
202 return camlzip_bzDecompress(arg
[0], arg
[1], arg
[2], arg
[3],
203 arg
[4], arg
[5], arg
[6]);
206 value
camlzip_bzDecompressEnd(value stream
) {
209 if ((err
= BZ2_bzDecompressEnd(BZStream_val(stream
))) != BZ_OK
)
210 camlzip_bzerror("Bzlib.decompressEnd", err
);
211 free(BZStream_val(stream
));
213 failwith("Bzip2 compression not supported");
218 int camlzip_bzlibversion(void)
222 #ifdef HAVE_BZLIBVERSION
223 v
= copy_string (BZ2_bzlibVersion());
226 failwith("bzlibVersion not found");