⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inflate.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#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);intinflateinit(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;}intinflate(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 intuncblock(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 intfixedblock(Input *in, History *his){	return decode(in, his, &litlentab, &offtab);}static intdynamicblock(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 intdecode(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 intrevcode(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 inthufftab(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 inthdecsym(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 intsregfill(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 intsregunget(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;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -