zlib.ml 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. (***********************************************************************)
  2. (* *)
  3. (* The CamlZip library *)
  4. (* *)
  5. (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
  6. (* adapted to Extc lib by Caue Waneck *)
  7. (* *)
  8. (* Copyright 2001 Institut National de Recherche en Informatique et *)
  9. (* en Automatique. All rights reserved. This file is distributed *)
  10. (* under the terms of the GNU Lesser General Public License, with *)
  11. (* the special exception on linking described in file LICENSE. *)
  12. (* *)
  13. (***********************************************************************)
  14. (* $Id: zlib.ml,v 1.4 2008/12/07 09:23:08 xleroy Exp $ *)
  15. open Extc;;
  16. let buffer_size = 1024
  17. let polynom = 0xedb88320l
  18. let crc_table = Array.init 256 (fun n ->
  19. let crc = ref (Int32.of_int n) in
  20. for j = 0 to 7 do
  21. crc := if Int32.to_int (Int32.logand (!crc) 1l) <> 0 then
  22. Int32.logxor (Int32.shift_right_logical (!crc) 1) polynom
  23. else
  24. Int32.shift_right_logical (!crc) 1;
  25. done;
  26. !crc)
  27. let max_wbits = 15
  28. let compress ?(level = 6) ?(header = true) refill flush =
  29. let inbuf = Bytes.create buffer_size
  30. and outbuf = Bytes.create buffer_size in
  31. let zs = Extc.zlib_deflate_init2 level (if header then max_wbits else -max_wbits) in
  32. let rec compr inpos inavail =
  33. if inavail = 0 then begin
  34. let incount = refill inbuf in
  35. if incount = 0 then compr_finish() else compr 0 incount
  36. end else begin
  37. let res = Extc.zlib_deflate zs ~src:(Bytes.to_string inbuf) ~spos:inpos ~slen:inavail ~dst:outbuf ~dpos:0 ~dlen:buffer_size Z_NO_FLUSH in
  38. let used_in, used_out = res.z_read, res.z_wrote in
  39. flush outbuf used_out;
  40. compr (inpos + used_in) (inavail - used_in)
  41. end
  42. and compr_finish () =
  43. let ret = Extc.zlib_deflate zs ~src:(Bytes.to_string inbuf) ~spos:0 ~slen:0 ~dst:outbuf ~dpos:0 ~dlen:buffer_size Z_FINISH in
  44. let (finished, _, used_out) = ret.z_finish, ret.z_read, ret.z_wrote in
  45. flush outbuf used_out;
  46. if not finished then compr_finish()
  47. in
  48. compr 0 0;
  49. Extc.zlib_deflate_end zs
  50. let compress_direct ?(level = 6) ?(header = true) flush =
  51. let outbuf = Bytes.create buffer_size in
  52. let zs = Extc.zlib_deflate_init2 level (if header then max_wbits else -max_wbits) in
  53. let rec compr inbuf inpos inavail =
  54. if inavail = 0 then ()
  55. else begin
  56. let res = Extc.zlib_deflate zs ~src:(Bytes.to_string inbuf) ~spos:inpos ~slen:inavail ~dst:outbuf ~dpos:0 ~dlen:buffer_size Z_NO_FLUSH in
  57. let used_in, used_out = res.z_read, res.z_wrote in
  58. flush outbuf used_out;
  59. compr inbuf (inpos + used_in) (inavail - used_in)
  60. end
  61. and compr_finish () =
  62. let ret = Extc.zlib_deflate zs ~src:"" ~spos:0 ~slen:0 ~dst:outbuf ~dpos:0 ~dlen:buffer_size Z_FINISH in
  63. let (finished, _, used_out) = ret.z_finish, (), ret.z_wrote in
  64. flush outbuf used_out;
  65. if not finished then compr_finish()
  66. in
  67. compr, compr_finish
  68. let uncompress ?(header = true) refill flush =
  69. let inbuf = Bytes.create buffer_size
  70. and outbuf = Bytes.create buffer_size in
  71. let zs = Extc.zlib_inflate_init2 (if header then max_wbits else -max_wbits) in
  72. let rec uncompr inpos inavail =
  73. if inavail = 0 then begin
  74. let incount = refill inbuf in
  75. if incount = 0 then uncompr_finish true else uncompr 0 incount
  76. end else begin
  77. let ret = Extc.zlib_inflate zs ~src:(Bytes.to_string inbuf) ~spos: inpos ~slen:inavail ~dst:outbuf ~dpos:0 ~dlen:buffer_size Z_SYNC_FLUSH in
  78. let (finished, used_in, used_out) = ret.z_finish, ret.z_read, ret.z_wrote in
  79. flush outbuf used_out;
  80. if not finished then uncompr (inpos + used_in) (inavail - used_in)
  81. end
  82. and uncompr_finish first_finish =
  83. (* Gotcha: if there is no header, inflate requires an extra "dummy" byte
  84. after the compressed stream in order to complete decompression
  85. and return finished = true. *)
  86. let dummy_byte = if first_finish && not header then 1 else 0 in
  87. let ret = Extc.zlib_inflate zs ~src:(Bytes.to_string inbuf) ~spos:0 ~slen:dummy_byte ~dst:outbuf ~dpos:0 ~dlen:buffer_size Z_SYNC_FLUSH in
  88. let (finished, _, used_out) = ret.z_finish, ret.z_read, ret.z_wrote in
  89. flush outbuf used_out;
  90. if not finished then uncompr_finish false
  91. in
  92. uncompr 0 0;
  93. Extc.zlib_inflate_end zs
  94. let update_crc crc buf pos len =
  95. let c = ref (Int32.lognot crc) in
  96. for i = pos to (len + pos - 1) do
  97. let b = Int32.of_int (int_of_char (Bytes.get buf i)) in
  98. c := Int32.logxor (Array.get crc_table (Int32.to_int (Int32.logand (Int32.logxor !c b) 0xFFl))) (Int32.shift_right_logical !c 8);
  99. done;
  100. let ret = Int32.lognot !c in
  101. ret