跳到正文
参考文档 / ZLIB × LEAN

gzwrite.c.lean

此页源文件快照 · af693d4593c6ea11 · 对应提交的原文 ↗

本页保留 Lean 源码及行号。点击行号可定位语句,点击 import 中的模块名可查看依赖。

1import ZlibF.Zlib.«gzlib.c»
2import ZlibF.Zlib.«deflate.c»
3
4/-!
5# gzwrite.c — faithful translation
6
7Source: `gzwrite.c` of the verified source (unpatched), default x86_64 Linux build. `STDC` is defined, so
8`gz_vacate`, `gzvprintf` and the `va_list` version of `gzprintf` are compiled; `HAVE_VSNPRINTF` is defined and
9`HAS_vsnprintf_void` is not, so the live call is `len = vsnprintf(next, state->size, format, va);`. The old-style
10`gzprintf` with twenty `int` arguments is not compiled.
11
12Decisions: `gzvprintf`/`gzprintf` take the variadic arguments as a list `VaArg` (`Zlib.GzFs`); `vsnprintf` is the
13model of `gzfs.lean`. `unsigned char buf[1]` of `gzputc` is a local block freed before every return.
14`write` goes through `GzFs.fsWrite`: the bytes it writes are read from the heap first (a fault if the range is not
15inside its object).
16-/
17
18namespace Zlib.Gzwrite
19open C Zlib.GzFs Zlib.Gzguts Zlib.Gzlib
20open Zlib.Deflate (deflateInit2_ deflateReset deflate deflateParams deflateEnd)
21
22/-- `local int gz_init(gz_statep state)` -/
23def gz_init (state : GzStatePtr) : G Int32 := do
24  let strm := strmOf state
25  -- state->in = (unsigned char *)malloc(state->want << 1);
26  let s ← ldS state
27  let inb ← allocB (s.want <<< 1).toNat
28  updS state fun s => { s with «in» := inb }
29  if inb == .null then
30    gz_error state Z_MEM_ERROR (← strLit "out of memory")
31    return -1
32  -- if (!state->direct) { ... }
33  let s ← ldS state
34  if s.direct == 0 then
35    -- state->out = (unsigned char *)malloc(state->want);
36    let outb ← allocB s.want.toNat
37    updS state fun s => { s with out := outb }
38    if outb == .null then
39      freeB (← ldS state).«in»
40      gz_error state Z_MEM_ERROR (← strLit "out of memory")
41      return -1
42    -- strm->zalloc = Z_NULL; strm->zfree = Z_NULL; strm->opaque = Z_NULL;
43    updZ strm fun z => { z with zalloc := .null, zfree := .null, «opaque» := .null }
44    -- ret = deflateInit2(strm, state->level, Z_DEFLATED, MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
45    let s ← ldS state
46    let ver ← strLit ZLIB_VERSION
47    let ret ← deflateInit2_ strm s.level Z_DEFLATED (MAX_WBITS + 16) DEF_MEM_LEVEL s.strategy ver 112
48    if ret != Z_OK then
49      let s ← ldS state
50      freeB s.out
51      freeB s.«in»
52      gz_error state Z_MEM_ERROR (← strLit "out of memory")
53      return -1
54  -- strm->next_in = NULL;
55  updZ strm fun z => { z with next_in := .null }
56  -- state->size = state->want;
57  updS state fun s => { s with size := s.want }
58  -- if (!state->direct) { strm->avail_out = state->size; strm->next_out = state->out; state->x.next = strm->next_out; }
59  let s ← ldS state
60  if s.direct == 0 then
61    updZ strm fun z => { z with avail_out := s.size, next_out := s.out }
62    let z ← ldZ strm
63    updX state fun x => { x with next := z.next_out }
64  return 0
65
66structure CompLoop where
67  ret : Int32
68  «have» : UInt32
69  res : Option Int32
70
71/-- `local int gz_comp(gz_statep state, int flush)`. `max` is `((unsigned)-1 >> 2) + 1`; the `return -1` inside the
72loops is the tag `res`. -/
73def gz_comp (state : GzStatePtr) (flush : Int32) : G Int32 := do
74  let strm := strmOf state
75  let max : UInt32 := (((0 : UInt32) - 1) >>> 2) + 1
76  -- if (state->size == 0 && gz_init(state) == -1) return -1;
77  if (← ldS state).size == 0 then
78    if (← gz_init state) == -1 then return -1
79  -- if (state->direct) { while (strm->avail_in) {...} return 0; }
80  if (← ldS state).direct != 0 then
81    let r ← gwhile
82      (fun (r : Option Int32) => do
83        if r.isSome then return (false, r)
84        return ((← ldZ strm).avail_in != 0, r))
85      (fun _ => do
86        setErrno 0
87        updS state fun s => { s with again := 0 }
88        let z ← ldZ strm
89        let s ← ldS state
90        let put : UInt32 := if z.avail_in > max then max else z.avail_in
91        let bs ← loadBytes z.next_in put.toNat
92        let writ := (← fsWrite s.fd bs).toInt32
93        if writ < 0 then
94          if BLOCKED (← getErrno) then updS state fun s => { s with again := 1 }
95          gz_error state Z_ERRNO (← zstrerror)
96          return some (-1)
97        let z ← ldZ strm
98        let np ← z.next_in.add writ.toInt
99        updZ strm fun z => { z with avail_in := z.avail_in - writ.toUInt32, next_in := np }
100        return none)
101      none
102    return r.getD 0
103  -- if (state->reset) { ... }
104  if (← ldS state).reset != 0 then
105    let z ← ldZ strm
106    if z.avail_in == 0 && flush == Z_NO_FLUSH then return 0
107    let _ ← deflateReset strm
108    updS state fun s => { s with reset := 0 }
109  -- ret = Z_OK; do { ... } while (have);
110  let l ← gdoWhile
111    (fun (l : CompLoop) => do
112      let z ← ldZ strm
113      let mut l := l
114      -- if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && (flush != Z_FINISH || ret == Z_STREAM_END))) {
115      if z.avail_out == 0 || (flush != Z_NO_FLUSH && (flush != Z_FINISH || l.ret == Z_STREAM_END)) then
116        -- while (strm->next_out > state->x.next) {
117        let r ← gwhile
118          (fun (r : Option Int32) => do
119            if r.isSome then return (false, r)
120            let z ← ldZ strm
121            let s ← ldS state
122            return (← Ptr.lt s.x.next z.next_out, r))
123          (fun _ => do
124            setErrno 0
125            updS state fun s => { s with again := 0 }
126            let z ← ldZ strm
127            let s ← ldS state
128            -- put = next_out - x.next > (int)max ? max : (unsigned)(next_out - x.next);
129            let d ← Ptr.diff z.next_out s.x.next
130            let put : UInt32 := if d > (Int64.ofNat max.toNat) then max else d.toUInt64.toUInt32
131            let bs ← loadBytes s.x.next put.toNat
132            let writ := (← fsWrite s.fd bs).toInt32
133            if writ < 0 then
134              if BLOCKED (← getErrno) then updS state fun s => { s with again := 1 }
135              gz_error state Z_ERRNO (← zstrerror)
136              return some (-1)
137            let s ← ldS state
138            let nx ← s.x.next.add writ.toInt
139            updX state fun x => { x with next := nx }
140            return none)
141          none
142        if r.isSome then return { l with res := r }
143        -- if (strm->avail_out == 0) { strm->avail_out = state->size; next_out = out; x.next = out; }
144        if (← ldZ strm).avail_out == 0 then
145          let s ← ldS state
146          updZ strm fun z => { z with avail_out := s.size, next_out := s.out }
147          updX state fun x => { x with next := s.out }
148      -- have = strm->avail_out; ret = deflate(strm, flush);
149      let hv := (← ldZ strm).avail_out
150      let ret ← deflate strm flush
151      if ret == Z_STREAM_ERROR then
152        gz_error state Z_STREAM_ERROR (← strLit "internal error: deflate stream corrupt")
153        return { l with ret, res := some (-1) }
154      -- have -= strm->avail_out;
155      return { l with ret, «have» := hv - (← ldZ strm).avail_out })
156    (fun l => pure (l.res.isNone && l.«have» != 0, l))
157    { ret := Z_OK, «have» := 0, res := none }
158  if let some r := l.res then return r
159  -- if (flush == Z_FINISH) state->reset = 1;
160  if flush == Z_FINISH then updS state fun s => { s with reset := 1 }
161  return 0
162
163structure ZeroLoop where
164  first : Bool
165  res : Option Int32
166
167/-- `local int gz_zero(gz_statep state)` -/
168def gz_zero (state : GzStatePtr) : G Int32 := do
169  let strm := strmOf state
170  -- if (state->size == 0 && gz_init(state) == -1) return -1;
171  if (← ldS state).size == 0 then
172    if (← gz_init state) == -1 then return -1
173  -- if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return -1;
174  if (← ldZ strm).avail_in != 0 then
175    if (← gz_comp state Z_NO_FLUSH) == -1 then return -1
176  -- first = 1; do { ... } while (state->skip);
177  let l ← gdoWhile
178    (fun (l : ZeroLoop) => do
179      let s ← ldS state
180      -- n = GT_OFF(state->size) || (z_off64_t)state->size > state->skip ? (unsigned)state->skip : state->size;
181      let mut n : UInt32 ← if (← GT_OFF s.size) || u32ToI64 s.size > s.skip then pure s.skip.toUInt64.toUInt32
182        else pure s.size
183      let mut first := l.first
184      if first then
185        memsetB s.«in» 0 n.toNat
186        first := false
187      -- strm->avail_in = n; strm->next_in = state->in; ret = gz_comp(state, Z_NO_FLUSH);
188      updZ strm fun z => { z with avail_in := n, next_in := s.«in» }
189      let ret ← gz_comp state Z_NO_FLUSH
190      -- n -= strm->avail_in; state->x.pos += n; state->skip -= n;
191      n := n - (← ldZ strm).avail_in
192      let s ← ldS state
193      let np ← i64add s.x.pos (u32ToI64 n)
194      updX state fun x => { x with pos := np }
195      let s ← ldS state
196      let sk ← i64sub s.skip (u32ToI64 n)
197      updS state fun s => { s with skip := sk }
198      if ret == -1 then
199        let s ← ldS state
200        updZ strm fun z => { z with avail_in := 0, next_in := s.«in» }
201        return { first, res := some (-1) }
202      return { first, res := none })
203    (fun l => do
204      if l.res.isSome then return (false, l)
205      return ((← ldS state).skip != 0, l))
206    { first := true, res := none }
207  return l.res.getD 0
208
209structure WriteLoop where
210  len : UInt64
211  buf : BPtr
212  res : Option UInt64
213  brk : Bool
214
215/-- `local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len)` -/
216def gz_write (state : GzStatePtr) (buf : BPtr) (len : UInt64) : G UInt64 := do
217  let strm := strmOf state
218  -- z_size_t put = len;
219  let put := len
220  -- if (len == 0) return 0;
221  if len == 0 then return 0
222  -- if (state->size == 0 && gz_init(state) == -1) return 0;
223  if (← ldS state).size == 0 then
224    if (← gz_init state) == -1 then return 0
225  -- if (state->skip && gz_zero(state) == -1) return 0;
226  if (← ldS state).skip != 0 then
227    if (← gz_zero state) == -1 then return 0
228  -- if (len < state->size) { for (;;) {...} }
229  if len < (← ldS state).size.toUInt64 then
230    let l ← gwhile
231      (fun (l : WriteLoop) => pure (!l.brk && l.res.isNone, l))
232      (fun (l : WriteLoop) => do
233        -- if (state->strm.avail_in == 0) state->strm.next_in = state->in;
234        if (← ldZ strm).avail_in == 0 then
235          let s ← ldS state
236          updZ strm fun z => { z with next_in := s.«in» }
237        -- have = (unsigned)((state->strm.next_in + state->strm.avail_in) - state->in);
238        let z ← ldZ strm
239        let s ← ldS state
240        let tp ← z.next_in.add z.avail_in.toNat
241        let hv : UInt32 := (← Ptr.diff tp s.«in»).toUInt64.toUInt32
242        -- copy = state->size - have; if (copy > len) copy = (unsigned)len;
243        let mut copy := s.size - hv
244        if copy.toUInt64 > l.len then copy := l.len.toUInt32
245        -- memcpy(state->in + have, buf, copy);
246        memcpyB (← s.«in».add hv.toNat) l.buf copy.toNat
247        -- state->strm.avail_in += copy; state->x.pos += copy;
248        updZ strm fun z => { z with avail_in := z.avail_in + copy }
249        let s ← ldS state
250        let np ← i64add s.x.pos (u32ToI64 copy)
251        updX state fun x => { x with pos := np }
252        -- buf = (const char *)buf + copy; len -= copy;
253        let buf ← l.buf.add copy.toNat
254        let len := l.len - copy.toUInt64
255        -- if (len == 0) break;
256        if len == 0 then return { l with buf, len, brk := true }
257        -- if (gz_comp(state, Z_NO_FLUSH) == -1) return state->again ? put - len : 0;
258        if (← gz_comp state Z_NO_FLUSH) == -1 then
259          return { l with buf, len, res := some (if (← ldS state).again != 0 then put - len else 0) }
260        return { l with buf, len })
261      { len, buf, res := none, brk := false }
262    if let some r := l.res then return r
263  else
264    -- if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return 0;
265    if (← ldZ strm).avail_in != 0 then
266      if (← gz_comp state Z_NO_FLUSH) == -1 then return 0
267    -- state->strm.next_in = (z_const Bytef *)buf;
268    updZ strm fun z => { z with next_in := buf }
269    -- do { unsigned n = (unsigned)-1; ... } while (len);
270    let l ← gdoWhile
271      (fun (l : WriteLoop) => do
272        let mut n : UInt32 := 0xFFFFFFFF
273        if n.toUInt64 > l.len then n := l.len.toUInt32
274        updZ strm fun z => { z with avail_in := n }
275        let ret ← gz_comp state Z_NO_FLUSH
276        n := n - (← ldZ strm).avail_in
277        let s ← ldS state
278        let np ← i64add s.x.pos (u32ToI64 n)
279        updX state fun x => { x with pos := np }
280        let len := l.len - n.toUInt64
281        if ret == -1 then
282          let s ← ldS state
283          updZ strm fun z => { z with avail_in := 0, next_in := s.«in» }
284          return { l with len, res := some (if s.again != 0 then put - len else 0) }
285        return { l with len })
286      (fun l => pure (l.res.isNone && l.len != 0, l))
287      { len, buf, res := none, brk := false }
288    if let some r := l.res then return r
289    -- state->strm.next_in = state->in;
290    let s ← ldS state
291    updZ strm fun z => { z with next_in := s.«in» }
292  -- return put;
293  return put
294
295/-- `int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len)` -/
296def gzwrite (file : GzFilePtr) (buf : BPtr) (len : UInt32) : G Int32 := do
297  if file.isNone then return 0
298  let state := castState file
299  let s ← ldS state
300  -- if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again)) return 0;
301  if s.mode != GZ_WRITE || (s.err != Z_OK && s.again == 0) then return 0
302  gz_error state Z_OK .null
303  -- if ((int)len < 0) { gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); return 0; }
304  if len.toInt32 < 0 then
305    gz_error state Z_DATA_ERROR (← strLit "requested length does not fit in int")
306    return 0
307  -- return (int)gz_write(state, buf, len);
308  return (← gz_write state buf len.toUInt64).toUInt32.toInt32
309
310/-- `z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems, gzFile file)` -/
311def gzfwrite (buf : BPtr) (size nitems : UInt64) (file : GzFilePtr) : G UInt64 := do
312  if file.isNone then return 0
313  let state := castState file
314  let s ← ldS state
315  if s.mode != GZ_WRITE || (s.err != Z_OK && s.again == 0) then return 0
316  gz_error state Z_OK .null
317  -- len = nitems * size; if (size && len / size != nitems) { ... return 0; }
318  let len := nitems * size
319  if size != 0 && len / size != nitems then
320    gz_error state Z_STREAM_ERROR (← strLit "request does not fit in a size_t")
321    return 0
322  -- return len ? gz_write(state, buf, len) / size : 0;
323  if len != 0 then return (← gz_write state buf len) / size else return 0
324
325/-- `int ZEXPORT gzputc(gzFile file, int c)` -/
326def gzputc (file : GzFilePtr) (c : Int32) : G Int32 := do
327  -- unsigned have; unsigned char buf[1];
328  if file.isNone then return -1
329  let state := castState file
330  let strm := strmOf state
331  let s ← ldS state
332  if s.mode != GZ_WRITE || (s.err != Z_OK && s.again == 0) then return -1
333  gz_error state Z_OK .null
334  -- if (state->skip && gz_zero(state) == -1) return -1;
335  if (← ldS state).skip != 0 then
336    if (← gz_zero state) == -1 then return -1
337  -- if (state->size) { ... }
338  if (← ldS state).size != 0 then
339    if (← ldZ strm).avail_in == 0 then
340      let s ← ldS state
341      updZ strm fun z => { z with next_in := s.«in» }
342    let z ← ldZ strm
343    let s ← ldS state
344    let tp ← z.next_in.add z.avail_in.toNat
345    let hv : UInt32 := (← Ptr.diff tp s.«in»).toUInt64.toUInt32
346    if hv < s.size then
347      store8 (← s.«in».add hv.toNat) c.toUInt32.toUInt8
348      updZ strm fun z => { z with avail_in := z.avail_in + 1 }
349      let np ← i64add s.x.pos 1
350      updX state fun x => { x with pos := np }
351      return c &&& 0xff
352  -- buf[0] = (unsigned char)c; if (gz_write(state, buf, 1) != 1) return -1; return c & 0xff;
353  let buf ← allocLocal 1
354  store8 buf c.toUInt32.toUInt8
355  let w ← gz_write state buf 1
356  freeB buf
357  if w != 1 then return -1
358  return c &&& 0xff
359
360/-- `int ZEXPORT gzputs(gzFile file, const char *s)` -/
361def gzputs (file : GzFilePtr) (str : BPtr) : G Int32 := do
362  if file.isNone then return -1
363  let state := castState file
364  let s ← ldS state
365  if s.mode != GZ_WRITE || (s.err != Z_OK && s.again == 0) then return -1
366  gz_error state Z_OK .null
367  -- len = strlen(s); if ((int)len < 0 || (unsigned)len != len) { ... return -1; }
368  let len ← strlenB str
369  if len.toUInt32.toInt32 < 0 || len.toUInt32.toUInt64 != len then
370    gz_error state Z_STREAM_ERROR (← strLit "string length does not fit in int")
371    return -1
372  -- put = gz_write(state, s, len); return len && put == 0 ? -1 : (int)put;
373  let put ← gz_write state str len
374  return if len != 0 && put == 0 then -1 else put.toUInt32.toInt32
375
376/-- `local int gz_vacate(gz_statep state)` -/
377def gz_vacate (state : GzStatePtr) : G Int32 := do
378  let strm := strmOf state
379  -- if (strm->next_in == NULL || strm->next_in + strm->avail_in <= state->in + state->size) return 0;
380  let z ← ldZ strm
381  if z.next_in == .null then return 0
382  let s ← ldS state
383  let a ← z.next_in.add z.avail_in.toNat
384  let b ← s.«in».add s.size.toNat
385  if (← Ptr.le a b) then return 0
386  -- (void)gz_comp(state, Z_NO_FLUSH);
387  let _ ← gz_comp state Z_NO_FLUSH
388  -- if (strm->avail_in == 0) { strm->next_in = state->in; return 0; }
389  if (← ldZ strm).avail_in == 0 then
390    let s ← ldS state
391    updZ strm fun z => { z with next_in := s.«in» }
392    return 0
393  -- memmove(state->in, strm->next_in, strm->avail_in); strm->next_in = state->in;
394  let z ← ldZ strm
395  let s ← ldS state
396  memmoveB s.«in» z.next_in z.avail_in.toNat
397  updZ strm fun z => { z with next_in := s.«in» }
398  -- return strm->avail_in > state->size;
399  return if (← ldZ strm).avail_in > s.size then 1 else 0
400
401/-- `int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)` -/
402def gzvprintf (file : GzFilePtr) (format : BPtr) (va : List VaArg) : G Int32 := do
403  if file.isNone then return Z_STREAM_ERROR
404  let state := castState file
405  let strm := strmOf state
406  let s ← ldS state
407  if s.mode != GZ_WRITE || (s.err != Z_OK && s.again == 0) then return Z_STREAM_ERROR
408  gz_error state Z_OK .null
409  -- if (state->size == 0 && gz_init(state) == -1) return state->err;
410  if (← ldS state).size == 0 then
411    if (← gz_init state) == -1 then return (← ldS state).err
412  -- if (state->skip && gz_zero(state) == -1) return state->err;
413  if (← ldS state).skip != 0 then
414    if (← gz_zero state) == -1 then return (← ldS state).err
415  -- ret = gz_vacate(state);
416  let ret ← gz_vacate state
417  let s ← ldS state
418  if s.err != 0 then
419    if ret != 0 && s.again != 0 then
420      gz_error state Z_BUF_ERROR (← strLit "stalled write on gzprintf")
421      return (← ldS state).err
422    if s.again == 0 then return s.err
423  -- if (strm->avail_in == 0) strm->next_in = state->in;
424  if (← ldZ strm).avail_in == 0 then
425    let s ← ldS state
426    updZ strm fun z => { z with next_in := s.«in» }
427  -- next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
428  let z ← ldZ strm
429  let s ← ldS state
430  let d ← Ptr.diff z.next_in s.«in»
431  let next ← (← s.«in».add d.toInt).add z.avail_in.toNat
432  -- next[state->size - 1] = 0;
433  store8 (← next.add (s.size - 1).toNat) 0
434  -- len = vsnprintf(next, state->size, format, va);
435  let len ← vsnprintf next s.size.toUInt64 format va
436  -- if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0) return 0;
437  if len == 0 || len.toUInt32 ≥ s.size then return 0
438  if (← index8 next (s.size - 1).toNat) != 0 then return 0
439  -- strm->avail_in += (unsigned)len; state->x.pos += len;
440  updZ strm fun z => { z with avail_in := z.avail_in + len.toUInt32 }
441  let s ← ldS state
442  let np ← i64add s.x.pos len.toInt64
443  updX state fun x => { x with pos := np }
444  -- ret = gz_vacate(state); if (ret) { ... }
445  let ret ← gz_vacate state
446  if ret != 0 then
447    updZ strm fun z => { z with avail_in := z.avail_in - len.toUInt32 }
448    let s ← ldS state
449    let np ← i64sub s.x.pos len.toInt64
450    updX state fun x => { x with pos := np }
451    if (← ldS state).again != 0 then
452      gz_error state Z_BUF_ERROR (← strLit "stalled write on gzprintf")
453    return (← ldS state).err
454  -- if (state->err && !state->again) return state->err; return len;
455  let s ← ldS state
456  if s.err != 0 && s.again == 0 then return s.err
457  return len
458
459/-- `int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)`: `va_start` / `gzvprintf` / `va_end`. -/
460def gzprintf (file : GzFilePtr) (format : BPtr) (va : List VaArg) : G Int32 :=
461  gzvprintf file format va
462
463/-- `int ZEXPORT gzflush(gzFile file, int flush)` -/
464def gzflush (file : GzFilePtr) (flush : Int32) : G Int32 := do
465  if file.isNone then return Z_STREAM_ERROR
466  let state := castState file
467  let s ← ldS state
468  if s.mode != GZ_WRITE || (s.err != Z_OK && s.again == 0) then return Z_STREAM_ERROR
469  gz_error state Z_OK .null
470  -- if (flush < 0 || flush > Z_FINISH) return Z_STREAM_ERROR;
471  if flush < 0 || flush > Z_FINISH then return Z_STREAM_ERROR
472  -- if (state->skip && gz_zero(state) == -1) return state->err;
473  if (← ldS state).skip != 0 then
474    if (← gz_zero state) == -1 then return (← ldS state).err
475  -- (void)gz_comp(state, flush); return state->err;
476  let _ ← gz_comp state flush
477  return (← ldS state).err
478
479/-- `int ZEXPORT gzsetparams(gzFile file, int level, int strategy)`. Candidate finding (unconfirmed): the result
480(`Z_BUF_ERROR`) of `deflateParams` is ignored and the new level and strategy are stored anyway; see
481`docs/design/external-io.md`. -/
482def gzsetparams (file : GzFilePtr) (level strategy : Int32) : G Int32 := do
483  if file.isNone then return Z_STREAM_ERROR
484  let state := castState file
485  let strm := strmOf state
486  let s ← ldS state
487  -- if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again) || state->direct) return Z_STREAM_ERROR;
488  if s.mode != GZ_WRITE || (s.err != Z_OK && s.again == 0) || s.direct != 0 then return Z_STREAM_ERROR
489  gz_error state Z_OK .null
490  -- if (level == state->level && strategy == state->strategy) return Z_OK;
491  let s ← ldS state
492  if level == s.level && strategy == s.strategy then return Z_OK
493  -- if (state->skip && gz_zero(state) == -1) return state->err;
494  if s.skip != 0 then
495    if (← gz_zero state) == -1 then return (← ldS state).err
496  -- if (state->size) { ... }
497  if (← ldS state).size != 0 then
498    if (← ldZ strm).avail_in != 0 then
499      if (← gz_comp state Z_BLOCK) == -1 then return (← ldS state).err
500    let _ ← deflateParams strm level strategy
501  -- state->level = level; state->strategy = strategy; return Z_OK;
502  updS state fun s => { s with level, strategy }
503  return Z_OK
504
505/-- `int ZEXPORT gzclose_w(gzFile file)` -/
506def gzclose_w (file : GzFilePtr) : G Int32 := do
507  let mut ret := Z_OK
508  if file.isNone then return Z_STREAM_ERROR
509  let state := castState file
510  let s ← ldS state
511  -- if (state->mode != GZ_WRITE) return Z_STREAM_ERROR;
512  if s.mode != GZ_WRITE then return Z_STREAM_ERROR
513  -- if (state->skip && gz_zero(state) == -1) ret = state->err;
514  if s.skip != 0 then
515    if (← gz_zero state) == -1 then ret := (← ldS state).err
516  -- if (gz_comp(state, Z_FINISH) == -1) ret = state->err;
517  if (← gz_comp state Z_FINISH) == -1 then ret := (← ldS state).err
518  -- if (state->size) { if (!state->direct) { (void)deflateEnd(&(state->strm)); free(state->out); } free(state->in); }
519  let s ← ldS state
520  if s.size != 0 then
521    if s.direct == 0 then
522      let _ ← deflateEnd (strmOf state)
523      freeB s.out
524    freeB s.«in»
525  -- gz_error(state, Z_OK, NULL); free(state->path);
526  gz_error state Z_OK .null
527  let s ← ldS state
528  freeB s.path
529  -- if (close(state->fd) == -1) ret = Z_ERRNO;
530  if (← fsClose s.fd) == -1 then ret := Z_ERRNO
531  -- free(state); return ret;
532  freeGzState state
533  return ret
534
535end Zlib.Gzwrite
ZLIB × LEAN

全局目录

当前位置gzwrite.c.lean