compiler/src/lib/s3/ZlibWriters.Mod
Norayr Chilingarian fcc5f1447d added GetName function to OakFiles;
ported BTrees, MD5, Zip, Zlib, ZlibBuffers, ZlibDeflate, ZlibInflate, ZlibReaders, ZlibWriters to compile with voc
2013-10-31 18:51:55 +04:00

161 lines
5 KiB
Modula-2

(* ETH Oberon, Copyright 2001 ETH Zuerich Institut fuer Computersysteme, ETH Zentrum, CH-8092 Zuerich.
Refer to the "General ETH Oberon System Source License" contract available at: http://www.oberon.ethz.ch/ *)
MODULE ZlibWriters; (** Stefan Walthert **)
IMPORT
Files := OakFiles, Zlib, ZlibBuffers, ZlibDeflate;
CONST
(** result codes **)
Ok* = ZlibDeflate.Ok; StreamEnd* = ZlibDeflate.StreamEnd;
StreamError* = ZlibDeflate.StreamError; DataError* = ZlibDeflate.DataError; BufError* = ZlibDeflate.BufError;
(** flush values **)
NoFlush* = ZlibDeflate.NoFlush;
SyncFlush* = ZlibDeflate.SyncFlush;
FullFlush* = ZlibDeflate.FullFlush;
(** compression levels **)
DefaultCompression* = ZlibDeflate.DefaultCompression; NoCompression* = ZlibDeflate.NoCompression;
BestSpeed* = ZlibDeflate.BestSpeed; BestCompression* = ZlibDeflate.BestCompression;
(** compression strategies **)
DefaultStrategy* = ZlibDeflate.DefaultStrategy; Filtered* = ZlibDeflate.Filtered; HuffmanOnly* = ZlibDeflate.HuffmanOnly;
BufSize = 10000H;
TYPE
(** structure for writing deflated data in a file **)
Writer* = RECORD
res-: LONGINT; (** current stream state **)
flush-: SHORTINT; (** flush strategy **)
wrapper-: BOOLEAN; (** if set, zlib header and checksum are generated **)
r: Files.Rider; (* file rider *)
pos: LONGINT; (* logical position in uncompressed input stream *)
crc32-: LONGINT; (** crc32 of uncompressed data **)
out: POINTER TO ARRAY BufSize OF CHAR; (* output buffer space *)
s: ZlibDeflate.Stream (* compression stream *)
END;
(** change deflate parameters within the writer **)
PROCEDURE SetParams*(VAR w: Writer; level, strategy, flush: SHORTINT);
BEGIN
IF flush IN {NoFlush, SyncFlush, FullFlush} THEN
ZlibDeflate.SetParams(w.s, level, strategy);
w.flush := flush;
w.res := w.s.res
ELSE
w.res := StreamError
END
END SetParams;
(** open writer on a Files.Rider **)
PROCEDURE Open*(VAR w: Writer; level, strategy, flush: SHORTINT; wrapper: BOOLEAN; r: Files.Rider);
BEGIN
IF flush IN {NoFlush, SyncFlush, FullFlush} THEN
w.flush := flush;
w.wrapper := wrapper;
ZlibDeflate.Open(w.s, level, strategy, FALSE);
IF w.s.res = Ok THEN
NEW(w.out); ZlibBuffers.Init(w.s.out, w.out^, 0, BufSize, BufSize);
w.crc32 := Zlib.CRC32(0, w.out^, -1, -1);
w.r := r;
w.res := Ok
ELSE
w.res := w.s.res
END
ELSE
w.res := StreamError
END
END Open;
(** write specified number of bytes from buffer into and return number of bytes actually written **)
PROCEDURE WriteBytes*(VAR w: Writer; VAR buf: ARRAY OF CHAR; offset, len: LONGINT; VAR written: LONGINT);
BEGIN
ASSERT((0 <= offset) & (0 <= len) & (len <= LEN(buf)), 110);
IF ~w.s.open THEN
w.res := StreamError; written := 0
ELSIF (w.res < Ok) OR (len <= 0) THEN
written := 0
ELSE
ZlibBuffers.Init(w.s.in, buf, offset, len, len);
WHILE (w.res = Ok) & (w.s.in.avail # 0) DO
IF (w.s.out.avail = 0) THEN
Files.WriteBytes(w.r, w.out^, BufSize);
ZlibBuffers.Rewrite(w.s.out)
END;
IF w.res = Ok THEN
ZlibDeflate.Deflate(w.s, w.flush);
w.res := w.s.res
END
END;
w.crc32 := Zlib.CRC32(w.crc32, buf, offset, len - w.s.in.avail);
written := len - w.s.in.avail
END;
END WriteBytes;
(** write byte **)
PROCEDURE Write*(VAR w: Writer; ch: CHAR);
VAR
buf: ARRAY 1 OF CHAR;
written: LONGINT;
BEGIN
buf[0] := ch;
WriteBytes(w, buf, 0, 1, written)
END Write;
(** close writer **)
PROCEDURE Close*(VAR w: Writer);
VAR
done: BOOLEAN;
len: LONGINT;
BEGIN
ASSERT(w.s.in.avail = 0, 110);
done := FALSE;
LOOP
len := BufSize - w.s.out.avail;
IF len # 0 THEN
Files.WriteBytes(w.r, w.out^, len);
ZlibBuffers.Rewrite(w.s.out)
END;
IF done THEN EXIT END;
ZlibDeflate.Deflate(w.s, ZlibDeflate.Finish);
IF (len = 0) & (w.s.res = BufError) THEN
w.res := Ok
ELSE
w.res := w.s.res
END;
done := (w.s.out.avail # 0) OR (w.res = StreamEnd);
IF (w.res # Ok) & (w.res # StreamEnd) THEN EXIT END
END;
ZlibDeflate.Close(w.s);
w.res := w.s.res
END Close;
(** compress srclen bytes from src to dst with specified level and strategy. dstlen returns how many bytes have been written. **)
PROCEDURE Compress*(VAR src, dst: Files.Rider; srclen: LONGINT; VAR dstlen: LONGINT; level, strategy: SHORTINT; VAR crc32: LONGINT; VAR res: LONGINT);
VAR
w: Writer; buf: ARRAY BufSize OF CHAR; totWritten, written, read: LONGINT;
BEGIN
Open(w, level, strategy, NoFlush, FALSE, dst);
IF w.res = Ok THEN
totWritten := 0;
REPEAT
IF (srclen - totWritten) >= BufSize THEN read := BufSize
ELSE read := srclen - totWritten
END;
Files.ReadBytes(src, buf, read);
WriteBytes(w, buf, 0, read - src.res, written);
INC(totWritten, written)
UNTIL (w.res # Ok) OR (totWritten >= srclen);
Close(w);
crc32 := w.crc32;
dstlen := Files.Pos(w.r) - Files.Pos(dst);
END;
res := w.res
END Compress;
END ZlibWriters.