1 exception Error
of string * string
4 Callback.register_exception
"Zlib.Error" (Error
("",""))
14 external deflate_init
: int -> bool -> stream
= "camlzip_deflateInit"
16 stream
-> string -> int -> int -> string -> int -> int -> flush_command
18 = "camlzip_deflate_bytecode" "camlzip_deflate"
19 external deflate_end
: stream
-> unit = "camlzip_deflateEnd"
21 external inflate_init
: bool -> stream
= "camlzip_inflateInit"
23 stream
-> string -> int -> int -> string -> int -> int -> flush_command
25 = "camlzip_inflate_bytecode" "camlzip_inflate"
26 external inflate_end
: stream
-> unit = "camlzip_inflateEnd"
28 external update_crc
: int32
-> string -> int -> int -> int32
29 = "camlzip_update_crc32"
31 external zlib_version
: unit -> string = "camlzip_zlibversion"
33 let zlib_version_num () =
40 let buffer_size = 1024
42 let compress ?
(level
= 6) ?
(header
= true) refill flush
=
43 let inbuf = String.create
buffer_size
44 and outbuf
= String.create
buffer_size in
45 let zs = deflate_init level header
in
46 let rec compr inpos inavail
=
47 if inavail
= 0 then begin
48 let incount = refill
inbuf in
49 if incount = 0 then compr_finish
() else compr 0 incount
51 let (_, used_in
, used_out
) =
52 deflate
zs inbuf inpos inavail outbuf
0 buffer_size Z_NO_FLUSH
in
53 flush outbuf used_out
;
54 compr (inpos
+ used_in
) (inavail
- used_in
)
57 let (finished
, _, used_out
) =
58 deflate
zs inbuf 0 0 outbuf
0 buffer_size Z_FINISH
in
59 flush outbuf used_out
;
60 if not finished
then compr_finish
()
66 let s'
= String.create
(2 * String.length
s) in
67 String.blit
s 0 s'
0 (String.length
s);
70 let compress_string ?
(level
= 6) inbuf =
71 let zs = deflate_init level
true in
72 let rec compr inpos outbuf outpos
=
73 let inavail = String.length
inbuf - inpos
in
74 let outavail = String.length outbuf
- outpos
in
76 then compr inpos
(grow_buffer outbuf
) outpos
78 let (finished
, used_in
, used_out
) =
79 deflate
zs inbuf inpos
inavail outbuf outpos
outavail
80 (if inavail = 0 then Z_FINISH
else Z_NO_FLUSH
) in
82 String.sub outbuf
0 (outpos
+ used_out
)
84 compr (inpos
+ used_in
) outbuf
(outpos
+ used_out
)
86 let res = compr 0 (String.create
(String.length
inbuf)) 0 in
90 (* header info from camlzip/gpl *)
91 let gzip_string ?
(level
= 6) inbuf =
92 if String.length
inbuf <= 0 then "" else
94 let zs = deflate_init level
false in
95 let out_crc = ref Int32.zero
in
96 let rec compr inpos outbuf outpos
=
97 let inavail = String.length
inbuf - inpos
in
98 let outavail = String.length outbuf
- outpos
in
100 then compr inpos
(grow_buffer outbuf
) outpos
102 let (finished
, used_in
, used_out
) =
103 deflate
zs inbuf inpos
inavail outbuf outpos
outavail
104 (if inavail = 0 then Z_FINISH
else Z_NO_FLUSH
) in
105 out_crc := update_crc
!out_crc inbuf inpos used_in
;
107 String.sub outbuf
0 (outpos
+ used_out
)
109 compr (inpos
+ used_in
) outbuf
(outpos
+ used_out
)
111 let res = compr 0 (String.create
(String.length
inbuf)) 0 in
113 let buf = Buffer.create
(18 + String.length
res) in
114 let write_int wbuf n
=
115 Buffer.add_char wbuf
(char_of_int n
)
117 let write_int32 wbuf n
=
120 Buffer.add_char wbuf
(char_of_int
(Int32.to_int
(Int32.logand
!r 0xffl
)));
121 r := Int32.shift_right_logical
!r 8
128 for i
= 1 to 4 do write_int buf 0 done;
131 Buffer.add_string
buf res;
132 write_int32 buf !out_crc;
133 write_int32 buf (Int32.of_int
(String.length
inbuf));
137 let uncompress ?
(header
= true) refill flush
=
138 let inbuf = String.create
buffer_size
139 and outbuf
= String.create
buffer_size in
140 let zs = inflate_init header
in
141 let rec uncompr inpos
inavail =
142 if inavail = 0 then begin
143 let incount = refill
inbuf in
144 if incount = 0 then uncompr_finish
true else uncompr 0 incount
146 let (finished
, used_in
, used_out
) =
147 inflate
zs inbuf inpos
inavail outbuf
0 buffer_size Z_SYNC_FLUSH
in
148 flush outbuf used_out
;
149 if not finished
then uncompr (inpos
+ used_in
) (inavail - used_in
)
151 and uncompr_finish first_finish
=
152 (* Gotcha: if there is no header, inflate requires an extra "dummy" byte
153 after the compressed stream in order to complete decompression
154 and return finished = true. *)
155 let dummy_byte = if first_finish
&& not header
then 1 else 0 in
156 let (finished
, _, used_out
) =
157 inflate
zs inbuf 0 dummy_byte outbuf
0 buffer_size Z_SYNC_FLUSH
in
158 flush outbuf used_out
;
159 if not finished
then uncompr_finish
false
164 let uncompress_string2 inbuf =
165 let zs = inflate_init
true in
166 let rec uncompr inpos outbuf outpos
=
167 let inavail = String.length
inbuf - inpos
in
168 let outavail = String.length outbuf
- outpos
in
170 then uncompr inpos
(grow_buffer outbuf
) outpos
172 let (finished
, used_in
, used_out
) =
173 inflate
zs inbuf inpos
inavail outbuf outpos
outavail Z_SYNC_FLUSH
in
175 String.sub outbuf
0 (outpos
+ used_out
)
177 uncompr (inpos
+ used_in
) outbuf
(outpos
+ used_out
)
179 let res = uncompr 0 (String.create
(2 * String.length
inbuf)) 0 in
183 let uncompress_string s =
184 let buf = Buffer.create
(2 * String.length
s) in
186 let len = String.length
s in
187 uncompress ~header
: true (fun b
->
188 let n = min
(String.length b
) (len - !pos) in
189 if n < 1 then 0 else begin
190 String.blit
s !pos b
0 n;
193 ) (fun s len -> Buffer.add_string
buf (String.sub
s 0 len));