File: zlib.ml

package info (click to toggle)
camlzip 1.01-17
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 192 kB
  • ctags: 252
  • sloc: ml: 924; ansic: 139; makefile: 120; sh: 98
file content (130 lines) | stat: -rw-r--r-- 4,288 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
exception Error of string * string

let _ =
  Callback.register_exception "Zlib.Error" (Error("",""))

type stream

type flush_command =
    Z_NO_FLUSH
  | Z_SYNC_FLUSH
  | Z_FULL_FLUSH
  | Z_FINISH

external deflate_init: int -> bool -> stream = "camlzip_deflateInit"
external deflate:
  stream -> string -> int -> int -> string -> int -> int -> flush_command
         -> bool * int * int
  = "camlzip_deflate_bytecode" "camlzip_deflate"
external deflate_end: stream -> unit = "camlzip_deflateEnd"

external inflate_init: bool -> stream = "camlzip_inflateInit"
external inflate:
  stream -> string -> int -> int -> string -> int -> int -> flush_command
         -> bool * int * int
  = "camlzip_inflate_bytecode" "camlzip_inflate"
external inflate_end: stream -> unit = "camlzip_inflateEnd"

external update_crc: int32 -> string -> int -> int -> int32
                   = "camlzip_update_crc32"

let buffer_size = 1024

let compress ?(level = 6) ?(header = true) refill flush =
  let inbuf = String.create buffer_size
  and outbuf = String.create buffer_size in
  let zs = deflate_init level header in
  let rec compr inpos inavail =
    if inavail = 0 then begin
      let incount = refill inbuf in
      if incount = 0 then compr_finish() else compr 0 incount
    end else begin
      let (_, used_in, used_out) =
        deflate zs inbuf inpos inavail outbuf 0 buffer_size Z_NO_FLUSH in
      flush outbuf used_out;
      compr (inpos + used_in) (inavail - used_in)
    end
  and compr_finish () =
    let (finished, _, used_out) =
       deflate zs inbuf 0 0 outbuf 0 buffer_size Z_FINISH in
    flush outbuf used_out;
    if not finished then compr_finish()
  in
    compr 0 0;
    deflate_end zs

let grow_buffer s =
  let s' = String.create (2 * String.length s) in
  String.blit s 0 s' 0 (String.length s);
  s'

(****
let compress_string ?(level = 6) inbuf =
  let zs = deflate_init level true in
  let rec compr inpos outbuf outpos =
    let inavail = String.length inbuf - inpos in
    let outavail = String.length outbuf - outpos in
    if outavail = 0
    then compr inpos (grow_buffer outbuf) outpos
    else begin
      let (finished, used_in, used_out) =
        deflate zs inbuf inpos inavail outbuf outpos outavail
                   (if inavail = 0 then Z_FINISH else Z_NO_FLUSH) in
      if finished then 
        String.sub outbuf 0 (outpos + used_out)
      else
        compr (inpos + used_in) outbuf (outpos + used_out)
    end in
  let res = compr 0 (String.create (String.length inbuf)) 0 in
  deflate_end zs;
  res
****)

let uncompress ?(header = true) refill flush =
  let inbuf = String.create buffer_size
  and outbuf = String.create buffer_size in
  let zs = inflate_init header in
  let rec uncompr inpos inavail =
    if inavail = 0 then begin
      let incount = refill inbuf in
      if incount = 0 then uncompr_finish true else uncompr 0 incount
    end else begin
      let (_, used_in, used_out) =
        inflate zs inbuf inpos inavail outbuf 0 buffer_size Z_SYNC_FLUSH in
      flush outbuf used_out;
      uncompr (inpos + used_in) (inavail - used_in)
    end
  and uncompr_finish first_finish =
    (* Gotcha: if there is no header, inflate requires an extra "dummy" byte
       after the compressed stream in order to complete decompression
       and return finished = true. *)
    let dummy_byte = if first_finish && not header then 1 else 0 in
    let (finished, _, used_out) =
       inflate zs inbuf 0 dummy_byte outbuf 0 buffer_size Z_SYNC_FLUSH in
    flush outbuf used_out;
    if not finished then uncompr_finish false
  in
    uncompr 0 0;
    inflate_end zs

(*****
let uncompress_string inbuf =
  let zs = inflate_init true in
  let rec uncompr inpos outbuf outpos =
    let inavail = String.length inbuf - inpos in
    let outavail = String.length outbuf - outpos in
    if outavail = 0
    then uncompr inpos (grow_buffer outbuf) outpos
    else begin
      let (finished, used_in, used_out) =
        inflate zs inbuf inpos inavail outbuf outpos outavail Z_SYNC_FLUSH in
      if finished then 
        String.sub outbuf 0 (outpos + used_out)
      else
        uncompr (inpos + used_in) outbuf (outpos + used_out)
    end in
  let res = uncompr 0 (String.create (2 * String.length inbuf)) 0 in
  inflate_end zs;
  res

*****)