summaryrefslogtreecommitdiff
path: root/appl
diff options
context:
space:
mode:
Diffstat (limited to 'appl')
-rw-r--r--appl/lib/deflate.b122
-rw-r--r--appl/lib/inflate.b103
2 files changed, 193 insertions, 32 deletions
diff --git a/appl/lib/deflate.b b/appl/lib/deflate.b
index ccfeafbe..500b3797 100644
--- a/appl/lib/deflate.b
+++ b/appl/lib/deflate.b
@@ -42,6 +42,7 @@ GZCRCPOLY: con int 16redb88320;
GZOSINFERNO: con GZOSUNIX;
+Hnone, Hgzip, Hzlib: con iota; # LZstate.headers
LZstate: adt
{
hist: array of byte; # [HistSize];
@@ -56,11 +57,13 @@ LZstate: adt
prevoff: int;
maxchars: int; # compressor tuning
maxdefer: int;
+ level: int;
- crctab: array of int;
+ crctab: array of int; # for gzip trailer
crc: int;
tot: int;
- headers: int;
+ sum: big; # for zlib trailer
+ headers: int; # which header to print, if any
outbuf: array of byte; # current output buffer;
out: int; # current position in the output buffer
@@ -287,22 +290,27 @@ start(param: string): chan of ref Rq
{
# param contains flags:
# [0-9] - compression level
+ # h gzip header/trailer
+ # z zlib header/trailer
# v verbose
# d debug
lz := ref LZstate;
- level := 6;
+ lz.level = 6;
lz.verbose = lz.debug = 0;
- lz.headers = 0;
+ lz.headers = Hnone;
lz.crc = lz.tot = 0;
+ lz.sum = big 1;
# XXX could also put filename and modification time in param
for (i := 0; i < len param; i++) {
case param[i] {
'0' to '9' =>
- level = param[i] - '0';
+ lz.level = param[i] - '0';
'v' =>
lz.verbose = 1;
'h' =>
- lz.headers = 1;
+ lz.headers = Hgzip;
+ 'z' =>
+ lz.headers = Hzlib;
'd' =>
lz.debug = 1;
}
@@ -345,17 +353,17 @@ start(param: string): chan of ref Rq
lz.dot = lz.me;
lz.bits = 0;
lz.nbits = 0;
- if(level < 5) {
+ if(lz.level < 5) {
lz.maxchars = 1;
lz.maxdefer = 0;
- } else if(level == 9) {
+ } else if(lz.level == 9) {
lz.maxchars = 4000;
lz.maxdefer = MaxMatch;
} else {
lz.maxchars = 200;
lz.maxdefer = MaxMatch / 4;
}
- if (lz.headers)
+ if (lz.headers == Hgzip)
lz.crctab = mkcrctab(GZCRCPOLY);
lz.c = chan of ref Rq;
lz.rc = chan of int;
@@ -383,8 +391,7 @@ deflate(lz: ref LZstate)
{
lz.c <-= ref Rq.Start(sys->pctl(0, nil));
- if (lz.headers)
- header(lz);
+ header(lz);
buf := array[DeflateBlock] of byte;
out := array[DeflateBlock + DeflateOut] of byte;
eof := 0;
@@ -393,8 +400,7 @@ deflate(lz: ref LZstate)
nbuf := 0;
if (!eof) {
(eof, nbuf) = fillbuf(lz, buf);
- if (lz.headers) # added by Roman Joel Pacheco
- inblock(lz, buf[0:nbuf]);
+ inblock(lz, buf[0:nbuf]);
}
if(eof && nbuf == 0 && nslop == 0) {
if(lz.nbits) {
@@ -405,8 +411,7 @@ deflate(lz: ref LZstate)
exit;
continue;
}
- if (lz.headers)
- footer(lz);
+ footer(lz);
lz.c <-= ref Rq.Finished(nil);
exit;
}
@@ -538,7 +543,7 @@ deflate(lz: ref LZstate)
}
}
-header(lz: ref LZstate)
+headergzip(lz: ref LZstate)
{
buf := array[20] of byte;
i := 0;
@@ -569,7 +574,44 @@ header(lz: ref LZstate)
exit;
}
-footer(lz: ref LZstate)
+headerzlib(lz: ref LZstate)
+{
+ CIshift: con 12;
+ CMdeflate: con 8;
+ CMshift: con 8;
+ LVshift: con 6;
+ LVfastest, LVfast, LVnormal, LVbest: con iota;
+
+ level := LVnormal;
+ if(lz.level < 6)
+ level = LVfastest;
+ else if(lz.level >= 9)
+ level = LVbest;
+
+ h := 0;
+ h |= 7<<CIshift; # value is: (log2 of window size)-8
+ h |= CMdeflate<<CMshift;
+ h |= level<<LVshift;
+ h += 31-(h%31);
+
+ buf := array[2] of byte;
+ buf[0] = byte (h>>8);
+ buf[1] = byte (h>>0);
+
+ lz.c <-= ref Rq.Result(buf, lz.rc);
+ if (<-lz.rc == -1)
+ exit;
+}
+
+header(lz: ref LZstate)
+{
+ case lz.headers {
+ Hgzip => headergzip(lz);
+ Hzlib => headerzlib(lz);
+ }
+}
+
+footergzip(lz: ref LZstate)
{
buf := array[8] of byte;
i := 0;
@@ -587,6 +629,28 @@ footer(lz: ref LZstate)
exit;
}
+footerzlib(lz: ref LZstate)
+{
+ buf := array[4] of byte;
+ i := 0;
+ buf[i++] = byte (lz.sum>>24);
+ buf[i++] = byte (lz.sum>>16);
+ buf[i++] = byte (lz.sum>>8);
+ buf[i++] = byte (lz.sum>>0);
+
+ lz.c <-= ref Rq.Result(buf, lz.rc);
+ if(<-lz.rc == -1)
+ exit;
+}
+
+footer(lz: ref LZstate)
+{
+ case lz.headers {
+ Hgzip => footergzip(lz);
+ Hzlib => footerzlib(lz);
+ }
+}
+
lzput(lz: ref LZstate, bits, nbits: int): int
{
bits = (bits << lz.nbits) | lz.bits;
@@ -1349,7 +1413,7 @@ mkcrctab(poly: int): array of int
return crctab;
}
-inblock(lz: ref LZstate, buf: array of byte)
+inblockcrc(lz: ref LZstate, buf: array of byte)
{
crc := lz.crc;
n := len buf;
@@ -1360,6 +1424,28 @@ inblock(lz: ref LZstate, buf: array of byte)
lz.tot += n;
}
+inblockadler(lz: ref LZstate, buf: array of byte)
+{
+ ZLADLERBASE: con big 65521;
+
+ s1 := lz.sum & big 16rffff;
+ s2 := (lz.sum>>16) & big 16rffff;
+
+ for(i := 0; i < len buf; i++) {
+ s1 = (s1 + big buf[i]) % ZLADLERBASE;
+ s2 = (s2 + s1) % ZLADLERBASE;
+ }
+ lz.sum = (s2<<16) + s1;
+}
+
+inblock(lz: ref LZstate, buf: array of byte)
+{
+ case lz.headers {
+ Hgzip => inblockcrc(lz, buf);
+ Hzlib => inblockadler(lz, buf);
+ }
+}
+
fatal(lz: ref LZstate, s: string)
{
lz.c <-= ref Rq.Error(s);
diff --git a/appl/lib/inflate.b b/appl/lib/inflate.b
index 0f4d6ba7..3ee2503a 100644
--- a/appl/lib/inflate.b
+++ b/appl/lib/inflate.b
@@ -135,6 +135,7 @@ offdec: ref DeHuff;
revtab: array of byte; # bit reversal for endian swap of huffman codes
mask: array of int; # for masking low-order n bits of an int
+Hnone, Hgzip, Hzlib: con iota; # State.headers
State: adt {
ibuf, obuf: array of byte;
c: chan of ref Rq;
@@ -145,7 +146,8 @@ State: adt {
hist: array of byte; # history buffer for lempel-ziv backward references
usehist: int; # == 1 if 'hist' is valid
crctab: array of int;
- crc, tot: int;
+ crc, tot: int; # for gzip trailer
+ sum: big; # for zlib trailer
reg: int; # 24-bit shift register
nbits: int; # number of valid bits in reg
@@ -226,9 +228,16 @@ start(params: string): chan of ref Rq
s.nbits = 0;
s.crc = 0;
s.tot = 0;
+ s.sum = big 1;
s.hist = array[Blocksize] of byte;
- s.headers = (params != nil && params[0] == 'h');
- if (s.headers)
+ s.headers = Hnone;
+ if(params != nil) {
+ if(params[0] == 'h')
+ s.headers = Hgzip;
+ if(params[0] == 'z')
+ s.headers = Hzlib;
+ }
+ if (s.headers == Hgzip)
s.crctab = mkcrctab(GZCRCPOLY);
spawn inflate(s);
return s.c;
@@ -237,8 +246,7 @@ start(params: string): chan of ref Rq
inflate(s: ref State)
{
s.c <-= ref Rq.Start(sys->pctl(0, nil));
- if (s.headers)
- header(s);
+ header(s);
for(;;) {
bfinal := getn(s, 1, 0);
@@ -268,23 +276,21 @@ inflate(s: ref State)
}
if(bfinal) {
if(s.out) {
- if (s.headers)
- outblock(s);
+ outblock(s);
s.c <- = ref Rq.Result(s.obuf[0:s.out], s.rc);
flag := <- s.rc;
if (flag == -1)
exit;
}
flushbits(s);
- if (s.headers)
- footer(s);
+ footer(s);
s.c <-= ref Rq.Finished(s.ibuf[s.in - s.nbits/8:s.ein]);
exit;
}
}
}
-header(s: ref State)
+headergzip(s: ref State)
{
if(byte getb(s) != GZMAGIC1 || byte getb(s) != GZMAGIC2)
fatal(s, "not a gzip file");
@@ -335,7 +341,33 @@ header(s: ref State)
}
}
-footer(s: ref State)
+headerzlib(s: ref State)
+{
+ Fdict: con 1<<5;
+ CMshift: con 8;
+ CMmask: con (1<<4)-1;
+ CMdeflate: con 8;
+
+ h := 0;
+ h |= getb(s)<<8;
+ h |= getb(s);
+ if(h % 31 != 0)
+ fatal(s, "invalid zlib header");
+ if(h&Fdict)
+ fatal(s, "preset dictionary not supported");
+ if(((h>>CMshift)&CMmask) != CMdeflate)
+ fatal(s, "zlib compression method not deflate");
+}
+
+header(s: ref State)
+{
+ case s.headers {
+ Hgzip => headergzip(s);
+ Hzlib => headerzlib(s);
+ }
+}
+
+footergzip(s: ref State)
{
fcrc := getword(s);
if(s.crc != fcrc)
@@ -345,6 +377,25 @@ footer(s: ref State)
fatal(s, sys->sprint("byte count mismatch: computed %d, expected %d", s.tot, ftot));
}
+footerzlib(s: ref State)
+{
+ sum := big 0;
+ sum = (sum<<8)|big getb(s);
+ sum = (sum<<8)|big getb(s);
+ sum = (sum<<8)|big getb(s);
+ sum = (sum<<8)|big getb(s);
+ if(sum != s.sum)
+ fatal(s, sys->sprint("adler32 mismatch: computed %bux, expected %bux", s.sum, sum));
+}
+
+footer(s: ref State)
+{
+ case s.headers {
+ Hgzip => footergzip(s);
+ Hzlib => footerzlib(s);
+ }
+}
+
getword(s: ref State): int
{
n := 0;
@@ -694,8 +745,7 @@ flushbits(s: ref State)
#
flushout(s: ref State)
{
- if (s.headers)
- outblock(s);
+ outblock(s);
s.c <-= ref Rq.Result(s.obuf[0:s.out], s.rc);
flag := <- s.rc;
if (flag == -1)
@@ -723,7 +773,7 @@ mkcrctab(poly: int): array of int
return crctab;
}
-outblock(s: ref State)
+outblockgzip(s: ref State)
{
buf := s.obuf;
n := s.out;
@@ -735,6 +785,31 @@ outblock(s: ref State)
s.tot += n;
}
+outblockzlib(s: ref State)
+{
+ ZLADLERBASE: con big 65521;
+
+ buf := s.obuf;
+ n := s.out;
+
+ s1 := s.sum & big 16rffff;
+ s2 := (s.sum>>16) & big 16rffff;
+
+ for(i := 0; i < n; i++) {
+ s1 = (s1 + big buf[i]) % ZLADLERBASE;
+ s2 = (s2 + s1) % ZLADLERBASE;
+ }
+ s.sum = (s2<<16) + s1;
+}
+
+outblock(s: ref State)
+{
+ case s.headers {
+ Hgzip => outblockgzip(s);
+ Hzlib => outblockzlib(s);
+ }
+}
+
#
# irrecoverable error; invariably denotes data corruption
#