mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-24 11:41:58 +00:00
add libflate
This commit is contained in:
parent
8a708fb239
commit
b6afd33e2f
13 changed files with 2558 additions and 0 deletions
72
src/libflate/adler.c
Normal file
72
src/libflate/adler.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <flate.h>
|
||||
|
||||
enum
|
||||
{
|
||||
ADLERITERS = 5552, /* max iters before can overflow 32 bits */
|
||||
ADLERBASE = 65521 /* largest prime smaller than 65536 */
|
||||
};
|
||||
|
||||
ulong
|
||||
adler32(ulong adler, void *vbuf, int n)
|
||||
{
|
||||
ulong s1, s2;
|
||||
uchar *buf, *ebuf;
|
||||
int m;
|
||||
|
||||
buf = vbuf;
|
||||
s1 = adler & 0xffff;
|
||||
s2 = (adler >> 16) & 0xffff;
|
||||
for(; n >= 16; n -= m){
|
||||
m = n;
|
||||
if(m > ADLERITERS)
|
||||
m = ADLERITERS;
|
||||
m &= ~15;
|
||||
for(ebuf = buf + m; buf < ebuf; buf += 16){
|
||||
s1 += buf[0];
|
||||
s2 += s1;
|
||||
s1 += buf[1];
|
||||
s2 += s1;
|
||||
s1 += buf[2];
|
||||
s2 += s1;
|
||||
s1 += buf[3];
|
||||
s2 += s1;
|
||||
s1 += buf[4];
|
||||
s2 += s1;
|
||||
s1 += buf[5];
|
||||
s2 += s1;
|
||||
s1 += buf[6];
|
||||
s2 += s1;
|
||||
s1 += buf[7];
|
||||
s2 += s1;
|
||||
s1 += buf[8];
|
||||
s2 += s1;
|
||||
s1 += buf[9];
|
||||
s2 += s1;
|
||||
s1 += buf[10];
|
||||
s2 += s1;
|
||||
s1 += buf[11];
|
||||
s2 += s1;
|
||||
s1 += buf[12];
|
||||
s2 += s1;
|
||||
s1 += buf[13];
|
||||
s2 += s1;
|
||||
s1 += buf[14];
|
||||
s2 += s1;
|
||||
s1 += buf[15];
|
||||
s2 += s1;
|
||||
}
|
||||
s1 %= ADLERBASE;
|
||||
s2 %= ADLERBASE;
|
||||
}
|
||||
if(n){
|
||||
for(ebuf = buf + n; buf < ebuf; buf++){
|
||||
s1 += buf[0];
|
||||
s2 += s1;
|
||||
}
|
||||
s1 %= ADLERBASE;
|
||||
s2 %= ADLERBASE;
|
||||
}
|
||||
return (s2 << 16) + s1;
|
||||
}
|
40
src/libflate/crc.c
Normal file
40
src/libflate/crc.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <flate.h>
|
||||
|
||||
ulong*
|
||||
mkcrctab(ulong poly)
|
||||
{
|
||||
ulong *crctab;
|
||||
ulong crc;
|
||||
int i, j;
|
||||
|
||||
crctab = malloc(256 * sizeof(ulong));
|
||||
if(crctab == nil)
|
||||
return nil;
|
||||
|
||||
for(i = 0; i < 256; i++){
|
||||
crc = i;
|
||||
for(j = 0; j < 8; j++){
|
||||
if(crc & 1)
|
||||
crc = (crc >> 1) ^ poly;
|
||||
else
|
||||
crc >>= 1;
|
||||
}
|
||||
crctab[i] = crc;
|
||||
}
|
||||
return crctab;
|
||||
}
|
||||
|
||||
ulong
|
||||
blockcrc(ulong *crctab, ulong crc, void *vbuf, int n)
|
||||
{
|
||||
uchar *buf, *ebuf;
|
||||
|
||||
crc ^= 0xffffffff;
|
||||
buf = vbuf;
|
||||
ebuf = buf + n;
|
||||
while(buf < ebuf)
|
||||
crc = crctab[(crc & 0xff) ^ *buf++] ^ (crc >> 8);
|
||||
return crc ^ 0xffffffff;
|
||||
}
|
1359
src/libflate/deflate.c
Normal file
1359
src/libflate/deflate.c
Normal file
File diff suppressed because it is too large
Load diff
56
src/libflate/deflateblock.c
Normal file
56
src/libflate/deflateblock.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <flate.h>
|
||||
|
||||
typedef struct Block Block;
|
||||
|
||||
struct Block
|
||||
{
|
||||
uchar *pos;
|
||||
uchar *limit;
|
||||
};
|
||||
|
||||
static int
|
||||
blread(void *vb, void *buf, int n)
|
||||
{
|
||||
Block *b;
|
||||
|
||||
b = vb;
|
||||
if(n > b->limit - b->pos)
|
||||
n = b->limit - b->pos;
|
||||
memmove(buf, b->pos, n);
|
||||
b->pos += n;
|
||||
return n;
|
||||
}
|
||||
|
||||
static int
|
||||
blwrite(void *vb, void *buf, int n)
|
||||
{
|
||||
Block *b;
|
||||
|
||||
b = vb;
|
||||
|
||||
if(n > b->limit - b->pos)
|
||||
n = b->limit - b->pos;
|
||||
memmove(b->pos, buf, n);
|
||||
b->pos += n;
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
deflateblock(uchar *dst, int dsize, uchar *src, int ssize, int level, int debug)
|
||||
{
|
||||
Block bd, bs;
|
||||
int ok;
|
||||
|
||||
bs.pos = src;
|
||||
bs.limit = src + ssize;
|
||||
|
||||
bd.pos = dst;
|
||||
bd.limit = dst + dsize;
|
||||
|
||||
ok = deflate(&bd, blwrite, &bs, blread, level, debug);
|
||||
if(ok != FlateOk)
|
||||
return ok;
|
||||
return bd.pos - dst;
|
||||
}
|
60
src/libflate/deflatezlib.c
Normal file
60
src/libflate/deflatezlib.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <flate.h>
|
||||
#include "zlib.h"
|
||||
|
||||
typedef struct ZRead ZRead;
|
||||
|
||||
struct ZRead
|
||||
{
|
||||
ulong adler;
|
||||
void *rr;
|
||||
int (*r)(void*, void*, int);
|
||||
};
|
||||
|
||||
static int
|
||||
zlread(void *vzr, void *buf, int n)
|
||||
{
|
||||
ZRead *zr;
|
||||
|
||||
zr = vzr;
|
||||
n = (*zr->r)(zr->rr, buf, n);
|
||||
if(n <= 0)
|
||||
return n;
|
||||
zr->adler = adler32(zr->adler, buf, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
deflatezlib(void *wr, int (*w)(void*, void*, int), void *rr, int (*r)(void*, void*, int), int level, int debug)
|
||||
{
|
||||
ZRead zr;
|
||||
uchar buf[4];
|
||||
int ok;
|
||||
|
||||
buf[0] = ZlibDeflate | ZlibWin32k;
|
||||
|
||||
/* bogus zlib encoding of compression level */
|
||||
buf[1] = ((level > 2) + (level > 5) + (level > 8)) << 6;
|
||||
|
||||
/* header check field */
|
||||
buf[1] |= 31 - ((buf[0] << 8) | buf[1]) % 31;
|
||||
if((*w)(wr, buf, 2) != 2)
|
||||
return FlateOutputFail;
|
||||
|
||||
zr.rr = rr;
|
||||
zr.r = r;
|
||||
zr.adler = 1;
|
||||
ok = deflate(wr, w, &zr, zlread, level, debug);
|
||||
if(ok != FlateOk)
|
||||
return ok;
|
||||
|
||||
buf[0] = zr.adler >> 24;
|
||||
buf[1] = zr.adler >> 16;
|
||||
buf[2] = zr.adler >> 8;
|
||||
buf[3] = zr.adler;
|
||||
if((*w)(wr, buf, 4) != 4)
|
||||
return FlateOutputFail;
|
||||
|
||||
return FlateOk;
|
||||
}
|
34
src/libflate/deflatezlibblock.c
Normal file
34
src/libflate/deflatezlibblock.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <flate.h>
|
||||
#include "zlib.h"
|
||||
|
||||
int
|
||||
deflatezlibblock(uchar *dst, int dsize, uchar *src, int ssize, int level, int debug)
|
||||
{
|
||||
ulong adler;
|
||||
int n;
|
||||
|
||||
if(dsize < 6)
|
||||
return FlateOutputFail;
|
||||
|
||||
n = deflateblock(dst + 2, dsize - 6, src, ssize, level, debug);
|
||||
if(n < 0)
|
||||
return n;
|
||||
|
||||
dst[0] = ZlibDeflate | ZlibWin32k;
|
||||
|
||||
/* bogus zlib encoding of compression level */
|
||||
dst[1] = ((level > 2) + (level > 5) + (level > 8)) << 6;
|
||||
|
||||
/* header check field */
|
||||
dst[1] |= 31 - ((dst[0] << 8) | dst[1]) % 31;
|
||||
|
||||
adler = adler32(1, src, ssize);
|
||||
dst[n + 2] = adler >> 24;
|
||||
dst[n + 3] = adler >> 16;
|
||||
dst[n + 4] = adler >> 8;
|
||||
dst[n + 5] = adler;
|
||||
|
||||
return n + 6;
|
||||
}
|
23
src/libflate/flateerr.c
Normal file
23
src/libflate/flateerr.c
Normal file
|
@ -0,0 +1,23 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <flate.h>
|
||||
|
||||
char *
|
||||
flateerr(int err)
|
||||
{
|
||||
switch(err){
|
||||
case FlateOk:
|
||||
return "no error";
|
||||
case FlateNoMem:
|
||||
return "out of memory";
|
||||
case FlateInputFail:
|
||||
return "input error";
|
||||
case FlateOutputFail:
|
||||
return "output error";
|
||||
case FlateCorrupted:
|
||||
return "corrupted data";
|
||||
case FlateInternal:
|
||||
return "internal error";
|
||||
}
|
||||
return "unknown error";
|
||||
}
|
693
src/libflate/inflate.c
Normal file
693
src/libflate/inflate.c
Normal file
|
@ -0,0 +1,693 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <flate.h>
|
||||
|
||||
enum {
|
||||
HistorySize= 32*1024,
|
||||
BufSize= 4*1024,
|
||||
MaxHuffBits= 17, /* maximum bits in a encoded code */
|
||||
Nlitlen= 288, /* number of litlen codes */
|
||||
Noff= 32, /* number of offset codes */
|
||||
Nclen= 19, /* number of codelen codes */
|
||||
LenShift= 10, /* code = len<<LenShift|code */
|
||||
LitlenBits= 7, /* number of bits in litlen decode table */
|
||||
OffBits= 6, /* number of bits in offset decode table */
|
||||
ClenBits= 6, /* number of bits in code len decode table */
|
||||
MaxFlatBits= LitlenBits,
|
||||
MaxLeaf= Nlitlen
|
||||
};
|
||||
|
||||
typedef struct Input Input;
|
||||
typedef struct History History;
|
||||
typedef struct Huff Huff;
|
||||
|
||||
struct Input
|
||||
{
|
||||
int error; /* first error encountered, or FlateOk */
|
||||
void *wr;
|
||||
int (*w)(void*, void*, int);
|
||||
void *getr;
|
||||
int (*get)(void*);
|
||||
ulong sreg;
|
||||
int nbits;
|
||||
};
|
||||
|
||||
struct History
|
||||
{
|
||||
uchar his[HistorySize];
|
||||
uchar *cp; /* current pointer in history */
|
||||
int full; /* his has been filled up at least once */
|
||||
};
|
||||
|
||||
struct Huff
|
||||
{
|
||||
int maxbits; /* max bits for any code */
|
||||
int minbits; /* min bits to get before looking in flat */
|
||||
int flatmask; /* bits used in "flat" fast decoding table */
|
||||
ulong flat[1<<MaxFlatBits];
|
||||
ulong maxcode[MaxHuffBits];
|
||||
ulong last[MaxHuffBits];
|
||||
ulong decode[MaxLeaf];
|
||||
};
|
||||
|
||||
/* litlen code words 257-285 extra bits */
|
||||
static int litlenextra[Nlitlen-257] =
|
||||
{
|
||||
/* 257 */ 0, 0, 0,
|
||||
/* 260 */ 0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
|
||||
/* 270 */ 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
|
||||
/* 280 */ 4, 5, 5, 5, 5, 0, 0, 0
|
||||
};
|
||||
|
||||
static int litlenbase[Nlitlen-257];
|
||||
|
||||
/* offset code word extra bits */
|
||||
static int offextra[Noff] =
|
||||
{
|
||||
0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
|
||||
4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
|
||||
9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
|
||||
0, 0,
|
||||
};
|
||||
static int offbase[Noff];
|
||||
|
||||
/* order code lengths */
|
||||
static int clenorder[Nclen] =
|
||||
{
|
||||
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
|
||||
};
|
||||
|
||||
/* for static huffman tables */
|
||||
static Huff litlentab;
|
||||
static Huff offtab;
|
||||
static uchar revtab[256];
|
||||
|
||||
static int uncblock(Input *in, History*);
|
||||
static int fixedblock(Input *in, History*);
|
||||
static int dynamicblock(Input *in, History*);
|
||||
static int sregfill(Input *in, int n);
|
||||
static int sregunget(Input *in);
|
||||
static int decode(Input*, History*, Huff*, Huff*);
|
||||
static int hufftab(Huff*, char*, int, int);
|
||||
static int hdecsym(Input *in, Huff *h, int b);
|
||||
|
||||
int
|
||||
inflateinit(void)
|
||||
{
|
||||
char *len;
|
||||
int i, j, base;
|
||||
|
||||
/* byte reverse table */
|
||||
for(i=0; i<256; i++)
|
||||
for(j=0; j<8; j++)
|
||||
if(i & (1<<j))
|
||||
revtab[i] |= 0x80 >> j;
|
||||
|
||||
for(i=257,base=3; i<Nlitlen; i++) {
|
||||
litlenbase[i-257] = base;
|
||||
base += 1<<litlenextra[i-257];
|
||||
}
|
||||
/* strange table entry in spec... */
|
||||
litlenbase[285-257]--;
|
||||
|
||||
for(i=0,base=1; i<Noff; i++) {
|
||||
offbase[i] = base;
|
||||
base += 1<<offextra[i];
|
||||
}
|
||||
|
||||
len = malloc(MaxLeaf);
|
||||
if(len == nil)
|
||||
return FlateNoMem;
|
||||
|
||||
/* static Litlen bit lengths */
|
||||
for(i=0; i<144; i++)
|
||||
len[i] = 8;
|
||||
for(i=144; i<256; i++)
|
||||
len[i] = 9;
|
||||
for(i=256; i<280; i++)
|
||||
len[i] = 7;
|
||||
for(i=280; i<Nlitlen; i++)
|
||||
len[i] = 8;
|
||||
|
||||
if(!hufftab(&litlentab, len, Nlitlen, MaxFlatBits))
|
||||
return FlateInternal;
|
||||
|
||||
/* static Offset bit lengths */
|
||||
for(i=0; i<Noff; i++)
|
||||
len[i] = 5;
|
||||
|
||||
if(!hufftab(&offtab, len, Noff, MaxFlatBits))
|
||||
return FlateInternal;
|
||||
free(len);
|
||||
|
||||
return FlateOk;
|
||||
}
|
||||
|
||||
int
|
||||
inflate(void *wr, int (*w)(void*, void*, int), void *getr, int (*get)(void*))
|
||||
{
|
||||
History *his;
|
||||
Input in;
|
||||
int final, type;
|
||||
|
||||
his = malloc(sizeof(History));
|
||||
if(his == nil)
|
||||
return FlateNoMem;
|
||||
his->cp = his->his;
|
||||
his->full = 0;
|
||||
in.getr = getr;
|
||||
in.get = get;
|
||||
in.wr = wr;
|
||||
in.w = w;
|
||||
in.nbits = 0;
|
||||
in.sreg = 0;
|
||||
in.error = FlateOk;
|
||||
|
||||
do {
|
||||
if(!sregfill(&in, 3))
|
||||
goto bad;
|
||||
final = in.sreg & 0x1;
|
||||
type = (in.sreg>>1) & 0x3;
|
||||
in.sreg >>= 3;
|
||||
in.nbits -= 3;
|
||||
switch(type) {
|
||||
default:
|
||||
in.error = FlateCorrupted;
|
||||
goto bad;
|
||||
case 0:
|
||||
/* uncompressed */
|
||||
if(!uncblock(&in, his))
|
||||
goto bad;
|
||||
break;
|
||||
case 1:
|
||||
/* fixed huffman */
|
||||
if(!fixedblock(&in, his))
|
||||
goto bad;
|
||||
break;
|
||||
case 2:
|
||||
/* dynamic huffman */
|
||||
if(!dynamicblock(&in, his))
|
||||
goto bad;
|
||||
break;
|
||||
}
|
||||
} while(!final);
|
||||
|
||||
if(his->cp != his->his && (*w)(wr, his->his, his->cp - his->his) != his->cp - his->his) {
|
||||
in.error = FlateOutputFail;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if(!sregunget(&in))
|
||||
goto bad;
|
||||
|
||||
free(his);
|
||||
if(in.error != FlateOk)
|
||||
return FlateInternal;
|
||||
return FlateOk;
|
||||
|
||||
bad:
|
||||
free(his);
|
||||
if(in.error == FlateOk)
|
||||
return FlateInternal;
|
||||
return in.error;
|
||||
}
|
||||
|
||||
static int
|
||||
uncblock(Input *in, History *his)
|
||||
{
|
||||
int len, nlen, c;
|
||||
uchar *hs, *hp, *he;
|
||||
|
||||
if(!sregunget(in))
|
||||
return 0;
|
||||
len = (*in->get)(in->getr);
|
||||
len |= (*in->get)(in->getr)<<8;
|
||||
nlen = (*in->get)(in->getr);
|
||||
nlen |= (*in->get)(in->getr)<<8;
|
||||
if(len != (~nlen&0xffff)) {
|
||||
in->error = FlateCorrupted;
|
||||
return 0;
|
||||
}
|
||||
|
||||
hp = his->cp;
|
||||
hs = his->his;
|
||||
he = hs + HistorySize;
|
||||
|
||||
while(len > 0) {
|
||||
c = (*in->get)(in->getr);
|
||||
if(c < 0)
|
||||
return 0;
|
||||
*hp++ = c;
|
||||
if(hp == he) {
|
||||
his->full = 1;
|
||||
if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
|
||||
in->error = FlateOutputFail;
|
||||
return 0;
|
||||
}
|
||||
hp = hs;
|
||||
}
|
||||
len--;
|
||||
}
|
||||
|
||||
his->cp = hp;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
fixedblock(Input *in, History *his)
|
||||
{
|
||||
return decode(in, his, &litlentab, &offtab);
|
||||
}
|
||||
|
||||
static int
|
||||
dynamicblock(Input *in, History *his)
|
||||
{
|
||||
Huff *lentab, *offtab;
|
||||
char *len;
|
||||
int i, j, n, c, nlit, ndist, nclen, res, nb;
|
||||
|
||||
if(!sregfill(in, 14))
|
||||
return 0;
|
||||
nlit = (in->sreg&0x1f) + 257;
|
||||
ndist = ((in->sreg>>5) & 0x1f) + 1;
|
||||
nclen = ((in->sreg>>10) & 0xf) + 4;
|
||||
in->sreg >>= 14;
|
||||
in->nbits -= 14;
|
||||
|
||||
if(nlit > Nlitlen || ndist > Noff || nlit < 257) {
|
||||
in->error = FlateCorrupted;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* huff table header */
|
||||
len = malloc(Nlitlen+Noff);
|
||||
lentab = malloc(sizeof(Huff));
|
||||
offtab = malloc(sizeof(Huff));
|
||||
if(len == nil || lentab == nil || offtab == nil){
|
||||
in->error = FlateNoMem;
|
||||
goto bad;
|
||||
}
|
||||
for(i=0; i < Nclen; i++)
|
||||
len[i] = 0;
|
||||
for(i=0; i<nclen; i++) {
|
||||
if(!sregfill(in, 3))
|
||||
goto bad;
|
||||
len[clenorder[i]] = in->sreg & 0x7;
|
||||
in->sreg >>= 3;
|
||||
in->nbits -= 3;
|
||||
}
|
||||
|
||||
if(!hufftab(lentab, len, Nclen, ClenBits)){
|
||||
in->error = FlateCorrupted;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
n = nlit+ndist;
|
||||
for(i=0; i<n;) {
|
||||
nb = lentab->minbits;
|
||||
for(;;){
|
||||
if(in->nbits<nb && !sregfill(in, nb))
|
||||
goto bad;
|
||||
c = lentab->flat[in->sreg & lentab->flatmask];
|
||||
nb = c & 0xff;
|
||||
if(nb > in->nbits){
|
||||
if(nb != 0xff)
|
||||
continue;
|
||||
c = hdecsym(in, lentab, c);
|
||||
if(c < 0)
|
||||
goto bad;
|
||||
}else{
|
||||
c >>= 8;
|
||||
in->sreg >>= nb;
|
||||
in->nbits -= nb;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(c < 16) {
|
||||
j = 1;
|
||||
} else if(c == 16) {
|
||||
if(in->nbits<2 && !sregfill(in, 2))
|
||||
goto bad;
|
||||
j = (in->sreg&0x3)+3;
|
||||
in->sreg >>= 2;
|
||||
in->nbits -= 2;
|
||||
if(i == 0) {
|
||||
in->error = FlateCorrupted;
|
||||
goto bad;
|
||||
}
|
||||
c = len[i-1];
|
||||
} else if(c == 17) {
|
||||
if(in->nbits<3 && !sregfill(in, 3))
|
||||
goto bad;
|
||||
j = (in->sreg&0x7)+3;
|
||||
in->sreg >>= 3;
|
||||
in->nbits -= 3;
|
||||
c = 0;
|
||||
} else if(c == 18) {
|
||||
if(in->nbits<7 && !sregfill(in, 7))
|
||||
goto bad;
|
||||
j = (in->sreg&0x7f)+11;
|
||||
in->sreg >>= 7;
|
||||
in->nbits -= 7;
|
||||
c = 0;
|
||||
} else {
|
||||
in->error = FlateCorrupted;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if(i+j > n) {
|
||||
in->error = FlateCorrupted;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
while(j) {
|
||||
len[i] = c;
|
||||
i++;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
if(!hufftab(lentab, len, nlit, LitlenBits)
|
||||
|| !hufftab(offtab, &len[nlit], ndist, OffBits)){
|
||||
in->error = FlateCorrupted;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
res = decode(in, his, lentab, offtab);
|
||||
|
||||
free(len);
|
||||
free(lentab);
|
||||
free(offtab);
|
||||
|
||||
return res;
|
||||
|
||||
bad:
|
||||
free(len);
|
||||
free(lentab);
|
||||
free(offtab);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
decode(Input *in, History *his, Huff *litlentab, Huff *offtab)
|
||||
{
|
||||
int len, off;
|
||||
uchar *hs, *hp, *hq, *he;
|
||||
int c;
|
||||
int nb;
|
||||
|
||||
hs = his->his;
|
||||
he = hs + HistorySize;
|
||||
hp = his->cp;
|
||||
|
||||
for(;;) {
|
||||
nb = litlentab->minbits;
|
||||
for(;;){
|
||||
if(in->nbits<nb && !sregfill(in, nb))
|
||||
return 0;
|
||||
c = litlentab->flat[in->sreg & litlentab->flatmask];
|
||||
nb = c & 0xff;
|
||||
if(nb > in->nbits){
|
||||
if(nb != 0xff)
|
||||
continue;
|
||||
c = hdecsym(in, litlentab, c);
|
||||
if(c < 0)
|
||||
return 0;
|
||||
}else{
|
||||
c >>= 8;
|
||||
in->sreg >>= nb;
|
||||
in->nbits -= nb;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(c < 256) {
|
||||
/* literal */
|
||||
*hp++ = c;
|
||||
if(hp == he) {
|
||||
his->full = 1;
|
||||
if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
|
||||
in->error = FlateOutputFail;
|
||||
return 0;
|
||||
}
|
||||
hp = hs;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if(c == 256)
|
||||
break;
|
||||
|
||||
if(c > 285) {
|
||||
in->error = FlateCorrupted;
|
||||
return 0;
|
||||
}
|
||||
|
||||
c -= 257;
|
||||
nb = litlenextra[c];
|
||||
if(in->nbits < nb && !sregfill(in, nb))
|
||||
return 0;
|
||||
len = litlenbase[c] + (in->sreg & ((1<<nb)-1));
|
||||
in->sreg >>= nb;
|
||||
in->nbits -= nb;
|
||||
|
||||
/* get offset */
|
||||
nb = offtab->minbits;
|
||||
for(;;){
|
||||
if(in->nbits<nb && !sregfill(in, nb))
|
||||
return 0;
|
||||
c = offtab->flat[in->sreg & offtab->flatmask];
|
||||
nb = c & 0xff;
|
||||
if(nb > in->nbits){
|
||||
if(nb != 0xff)
|
||||
continue;
|
||||
c = hdecsym(in, offtab, c);
|
||||
if(c < 0)
|
||||
return 0;
|
||||
}else{
|
||||
c >>= 8;
|
||||
in->sreg >>= nb;
|
||||
in->nbits -= nb;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(c > 29) {
|
||||
in->error = FlateCorrupted;
|
||||
return 0;
|
||||
}
|
||||
|
||||
nb = offextra[c];
|
||||
if(in->nbits < nb && !sregfill(in, nb))
|
||||
return 0;
|
||||
|
||||
off = offbase[c] + (in->sreg & ((1<<nb)-1));
|
||||
in->sreg >>= nb;
|
||||
in->nbits -= nb;
|
||||
|
||||
hq = hp - off;
|
||||
if(hq < hs) {
|
||||
if(!his->full) {
|
||||
in->error = FlateCorrupted;
|
||||
return 0;
|
||||
}
|
||||
hq += HistorySize;
|
||||
}
|
||||
|
||||
/* slow but correct */
|
||||
while(len) {
|
||||
*hp = *hq;
|
||||
hq++;
|
||||
hp++;
|
||||
if(hq >= he)
|
||||
hq = hs;
|
||||
if(hp == he) {
|
||||
his->full = 1;
|
||||
if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
|
||||
in->error = FlateOutputFail;
|
||||
return 0;
|
||||
}
|
||||
hp = hs;
|
||||
}
|
||||
len--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
his->cp = hp;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
revcode(int c, int b)
|
||||
{
|
||||
/* shift encode up so it starts on bit 15 then reverse */
|
||||
c <<= (16-b);
|
||||
c = revtab[c>>8] | (revtab[c&0xff]<<8);
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
* construct the huffman decoding arrays and a fast lookup table.
|
||||
* the fast lookup is a table indexed by the next flatbits bits,
|
||||
* which returns the symbol matched and the number of bits consumed,
|
||||
* or the minimum number of bits needed and 0xff if more than flatbits
|
||||
* bits are needed.
|
||||
*
|
||||
* flatbits can be longer than the smallest huffman code,
|
||||
* because shorter codes are assigned smaller lexical prefixes.
|
||||
* this means assuming zeros for the next few bits will give a
|
||||
* conservative answer, in the sense that it will either give the
|
||||
* correct answer, or return the minimum number of bits which
|
||||
* are needed for an answer.
|
||||
*/
|
||||
static int
|
||||
hufftab(Huff *h, char *hb, int maxleaf, int flatbits)
|
||||
{
|
||||
ulong bitcount[MaxHuffBits];
|
||||
ulong c, fc, ec, mincode, code, nc[MaxHuffBits];
|
||||
int i, b, minbits, maxbits;
|
||||
|
||||
for(i = 0; i < MaxHuffBits; i++)
|
||||
bitcount[i] = 0;
|
||||
maxbits = -1;
|
||||
minbits = MaxHuffBits + 1;
|
||||
for(i=0; i < maxleaf; i++){
|
||||
b = hb[i];
|
||||
if(b){
|
||||
bitcount[b]++;
|
||||
if(b < minbits)
|
||||
minbits = b;
|
||||
if(b > maxbits)
|
||||
maxbits = b;
|
||||
}
|
||||
}
|
||||
|
||||
h->maxbits = maxbits;
|
||||
if(maxbits <= 0){
|
||||
h->maxbits = 0;
|
||||
h->minbits = 0;
|
||||
h->flatmask = 0;
|
||||
return 1;
|
||||
}
|
||||
code = 0;
|
||||
c = 0;
|
||||
for(b = 0; b <= maxbits; b++){
|
||||
h->last[b] = c;
|
||||
c += bitcount[b];
|
||||
mincode = code << 1;
|
||||
nc[b] = mincode;
|
||||
code = mincode + bitcount[b];
|
||||
if(code > (1 << b))
|
||||
return 0;
|
||||
h->maxcode[b] = code - 1;
|
||||
h->last[b] += code - 1;
|
||||
}
|
||||
|
||||
if(flatbits > maxbits)
|
||||
flatbits = maxbits;
|
||||
h->flatmask = (1 << flatbits) - 1;
|
||||
if(minbits > flatbits)
|
||||
minbits = flatbits;
|
||||
h->minbits = minbits;
|
||||
|
||||
b = 1 << flatbits;
|
||||
for(i = 0; i < b; i++)
|
||||
h->flat[i] = ~0;
|
||||
|
||||
/*
|
||||
* initialize the flat table to include the minimum possible
|
||||
* bit length for each code prefix
|
||||
*/
|
||||
for(b = maxbits; b > flatbits; b--){
|
||||
code = h->maxcode[b];
|
||||
if(code == -1)
|
||||
break;
|
||||
mincode = code + 1 - bitcount[b];
|
||||
mincode >>= b - flatbits;
|
||||
code >>= b - flatbits;
|
||||
for(; mincode <= code; mincode++)
|
||||
h->flat[revcode(mincode, flatbits)] = (b << 8) | 0xff;
|
||||
}
|
||||
|
||||
for(i = 0; i < maxleaf; i++){
|
||||
b = hb[i];
|
||||
if(b <= 0)
|
||||
continue;
|
||||
c = nc[b]++;
|
||||
if(b <= flatbits){
|
||||
code = (i << 8) | b;
|
||||
ec = (c + 1) << (flatbits - b);
|
||||
if(ec > (1<<flatbits))
|
||||
return 0; /* this is actually an internal error */
|
||||
for(fc = c << (flatbits - b); fc < ec; fc++)
|
||||
h->flat[revcode(fc, flatbits)] = code;
|
||||
}
|
||||
if(b > minbits){
|
||||
c = h->last[b] - c;
|
||||
if(c >= maxleaf)
|
||||
return 0;
|
||||
h->decode[c] = i;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
hdecsym(Input *in, Huff *h, int nb)
|
||||
{
|
||||
long c;
|
||||
|
||||
if((nb & 0xff) == 0xff)
|
||||
nb = nb >> 8;
|
||||
else
|
||||
nb = nb & 0xff;
|
||||
for(; nb <= h->maxbits; nb++){
|
||||
if(in->nbits<nb && !sregfill(in, nb))
|
||||
return -1;
|
||||
c = revtab[in->sreg&0xff]<<8;
|
||||
c |= revtab[(in->sreg>>8)&0xff];
|
||||
c >>= (16-nb);
|
||||
if(c <= h->maxcode[nb]){
|
||||
in->sreg >>= nb;
|
||||
in->nbits -= nb;
|
||||
return h->decode[h->last[nb] - c];
|
||||
}
|
||||
}
|
||||
in->error = FlateCorrupted;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
sregfill(Input *in, int n)
|
||||
{
|
||||
int c;
|
||||
|
||||
while(n > in->nbits) {
|
||||
c = (*in->get)(in->getr);
|
||||
if(c < 0){
|
||||
in->error = FlateInputFail;
|
||||
return 0;
|
||||
}
|
||||
in->sreg |= c<<in->nbits;
|
||||
in->nbits += 8;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
sregunget(Input *in)
|
||||
{
|
||||
if(in->nbits >= 8) {
|
||||
in->error = FlateInternal;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* throw other bits on the floor */
|
||||
in->nbits = 0;
|
||||
in->sreg = 0;
|
||||
return 1;
|
||||
}
|
54
src/libflate/inflateblock.c
Normal file
54
src/libflate/inflateblock.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <flate.h>
|
||||
|
||||
typedef struct Block Block;
|
||||
|
||||
struct Block
|
||||
{
|
||||
uchar *pos;
|
||||
uchar *limit;
|
||||
};
|
||||
|
||||
static int
|
||||
blgetc(void *vb)
|
||||
{
|
||||
Block *b;
|
||||
|
||||
b = vb;
|
||||
if(b->pos >= b->limit)
|
||||
return -1;
|
||||
return *b->pos++;
|
||||
}
|
||||
|
||||
static int
|
||||
blwrite(void *vb, void *buf, int n)
|
||||
{
|
||||
Block *b;
|
||||
|
||||
b = vb;
|
||||
|
||||
if(n > b->limit - b->pos)
|
||||
n = b->limit - b->pos;
|
||||
memmove(b->pos, buf, n);
|
||||
b->pos += n;
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
inflateblock(uchar *dst, int dsize, uchar *src, int ssize)
|
||||
{
|
||||
Block bd, bs;
|
||||
int ok;
|
||||
|
||||
bs.pos = src;
|
||||
bs.limit = src + ssize;
|
||||
|
||||
bd.pos = dst;
|
||||
bd.limit = dst + dsize;
|
||||
|
||||
ok = inflate(&bd, blwrite, &bs, blgetc);
|
||||
if(ok != FlateOk)
|
||||
return ok;
|
||||
return bd.pos - dst;
|
||||
}
|
66
src/libflate/inflatezlib.c
Normal file
66
src/libflate/inflatezlib.c
Normal file
|
@ -0,0 +1,66 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <flate.h>
|
||||
#include "zlib.h"
|
||||
|
||||
typedef struct ZWrite ZWrite;
|
||||
|
||||
struct ZWrite
|
||||
{
|
||||
ulong adler;
|
||||
void *wr;
|
||||
int (*w)(void*, void*, int);
|
||||
};
|
||||
|
||||
static int
|
||||
zlwrite(void *vzw, void *buf, int n)
|
||||
{
|
||||
ZWrite *zw;
|
||||
|
||||
zw = vzw;
|
||||
zw->adler = adler32(zw->adler, buf, n);
|
||||
n = (*zw->w)(zw->wr, buf, n);
|
||||
if(n <= 0)
|
||||
return n;
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
inflatezlib(void *wr, int (*w)(void*, void*, int), void *getr, int (*get)(void*))
|
||||
{
|
||||
ZWrite zw;
|
||||
ulong v;
|
||||
int c, i;
|
||||
|
||||
c = (*get)(getr);
|
||||
if(c < 0)
|
||||
return FlateInputFail;
|
||||
i = (*get)(getr);
|
||||
if(i < 0)
|
||||
return FlateInputFail;
|
||||
|
||||
if(((c << 8) | i) % 31)
|
||||
return FlateCorrupted;
|
||||
if((c & ZlibMeth) != ZlibDeflate
|
||||
|| (c & ZlibCInfo) > ZlibWin32k)
|
||||
return FlateCorrupted;
|
||||
|
||||
zw.wr = wr;
|
||||
zw.w = w;
|
||||
zw.adler = 1;
|
||||
i = inflate(&zw, zlwrite, getr, get);
|
||||
if(i != FlateOk)
|
||||
return i;
|
||||
|
||||
v = 0;
|
||||
for(i = 0; i < 4; i++){
|
||||
c = (*get)(getr);
|
||||
if(c < 0)
|
||||
return FlateInputFail;
|
||||
v = (v << 8) | c;
|
||||
}
|
||||
if(zw.adler != v)
|
||||
return FlateCorrupted;
|
||||
|
||||
return FlateOk;
|
||||
}
|
68
src/libflate/inflatezlibblock.c
Normal file
68
src/libflate/inflatezlibblock.c
Normal file
|
@ -0,0 +1,68 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <flate.h>
|
||||
#include "zlib.h"
|
||||
|
||||
typedef struct Block Block;
|
||||
|
||||
struct Block
|
||||
{
|
||||
uchar *pos;
|
||||
uchar *limit;
|
||||
};
|
||||
|
||||
static int
|
||||
blgetc(void *vb)
|
||||
{
|
||||
Block *b;
|
||||
|
||||
b = vb;
|
||||
if(b->pos >= b->limit)
|
||||
return -1;
|
||||
return *b->pos++;
|
||||
}
|
||||
|
||||
static int
|
||||
blwrite(void *vb, void *buf, int n)
|
||||
{
|
||||
Block *b;
|
||||
|
||||
b = vb;
|
||||
|
||||
if(n > b->limit - b->pos)
|
||||
n = b->limit - b->pos;
|
||||
memmove(b->pos, buf, n);
|
||||
b->pos += n;
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
inflatezlibblock(uchar *dst, int dsize, uchar *src, int ssize)
|
||||
{
|
||||
Block bd, bs;
|
||||
int ok;
|
||||
|
||||
if(ssize < 6)
|
||||
return FlateInputFail;
|
||||
|
||||
if(((src[0] << 8) | src[1]) % 31)
|
||||
return FlateCorrupted;
|
||||
if((src[0] & ZlibMeth) != ZlibDeflate
|
||||
|| (src[0] & ZlibCInfo) > ZlibWin32k)
|
||||
return FlateCorrupted;
|
||||
|
||||
bs.pos = src + 2;
|
||||
bs.limit = src + ssize - 6;
|
||||
|
||||
bd.pos = dst;
|
||||
bd.limit = dst + dsize;
|
||||
|
||||
ok = inflate(&bd, blwrite, &bs, blgetc);
|
||||
if(ok != FlateOk)
|
||||
return ok;
|
||||
|
||||
if(adler32(1, dst, bs.pos - dst) != ((bs.pos[0] << 24) | (bs.pos[1] << 16) | (bs.pos[2] << 8) | bs.pos[3]))
|
||||
return FlateCorrupted;
|
||||
|
||||
return bd.pos - dst;
|
||||
}
|
22
src/libflate/mkfile
Normal file
22
src/libflate/mkfile
Normal file
|
@ -0,0 +1,22 @@
|
|||
PLAN9=../..
|
||||
<$PLAN9/src/mkhdr
|
||||
|
||||
LIB=libflate.a
|
||||
OFILES=\
|
||||
deflate.$O\
|
||||
deflatezlib.$O\
|
||||
deflateblock.$O\
|
||||
deflatezlibblock.$O\
|
||||
inflate.$O\
|
||||
inflatezlib.$O\
|
||||
inflateblock.$O\
|
||||
inflatezlibblock.$O\
|
||||
flateerr.$O\
|
||||
crc.$O\
|
||||
adler.$O\
|
||||
|
||||
HFILES=\
|
||||
$PLAN9/include/flate.h\
|
||||
zlib.h\
|
||||
|
||||
<$PLAN9/src/mksyslib
|
11
src/libflate/zlib.h
Normal file
11
src/libflate/zlib.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* zlib header fields
|
||||
*/
|
||||
enum
|
||||
{
|
||||
ZlibMeth = 0x0f, /* mask of compression methods */
|
||||
ZlibDeflate = 0x08,
|
||||
|
||||
ZlibCInfo = 0xf0, /* mask of compression aux. info */
|
||||
ZlibWin32k = 0x70, /* 32k history window */
|
||||
};
|
Loading…
Reference in a new issue