📄 ungzip.cpp
字号:
#include "ungzip.h"
//#define DEBUG 1
ush mask_bits[] =
{
0x0000,
0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
};
unsigned border[] = { /* Order of the bit length code lengths */
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
ush cplens[] = { /* Copy lengths for literal codes 257..285 */
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
/* note: see note #13 above about the 258 in this list. */
ush cplext[] = { /* Extra bits for literal codes 257..285 */
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */
ush cpdist[] = { /* Copy offsets for distance codes 0..29 */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577};
ush cpdext[] = { /* Extra bits for distance codes */
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};
int lbits = 9; /* bits in base literal/length lookup table */
int dbits = 6; /* bits in base distance lookup table */
Cunzip::Cunzip()
{
inbuf=new char[64*1024*1024];
outbuf=new char[64*1024*1024];
windown=new char[64*1024*1024];
}
Cunzip::~Cunzip()
{
}
void Cunzip::clear_bufs()
{
m_ioutcnt = 0;
m_iinsize = m_iinptr = 0;
//m_iinoffset
m_ibytes_in = m_ibytes_out = 0;
m_bover=false;
#ifdef DEBUG
m_fp=fopen("log/zout","w");
if(m_fp!=NULL)
fclose(m_fp);
#endif
}
/* ===========================================================================
* Fill the input buffer. This is called only when the buffer is empty.
*/
int Cunzip::fill_inbuf()
{
//int len;
/* Read as much as possible */
m_iinsize = 0;
//printf("m_iinlen=[%d]\n",m_iinlen);
if(m_iinlen<=0)
{
printf("to return eof in fill_inbuf\n");
//getchar();
m_bover=true;
return EOF;
}
//getchar();
if(m_iinlen>=INBUFSIZ)
{
memcpy(inbuf,m_szinput+m_ibytes_in,INBUFSIZ);
m_iinsize=INBUFSIZ;
m_iinlen-=INBUFSIZ;
}
else
{
memcpy(inbuf,m_szinput+m_ibytes_in,m_iinlen);
m_iinsize=m_iinlen;
m_iinlen=0;
}
m_ibytes_in +=m_iinsize;
m_iinptr = 1;
return inbuf[0];
}
void Cunzip::flush_window()
{
if (m_ioutcnt == 0) return;
//updcrc(window, m_ioutcnt);
printf("flush win%d %d\n",m_ibytes_out,m_ioutcnt);
memcpy(m_szoutput+m_ibytes_out,windown,m_ioutcnt);
#ifdef DEBUG
m_fp=fopen("log/zout","a");
if(m_fp!=NULL)
{
fwrite(windown,m_ioutcnt,1,m_fp);
fclose(m_fp);
}
#endif
m_ibytes_out += m_ioutcnt;
m_ioutcnt = 0;
}
int Cunzip::get_method()
/* input file descriptor */
{
uch flags; /* compression flags */
char magic[2]; /* magic header */
ulg stamp; /* time stamp */
magic[0] = (char)(m_iinptr < m_iinsize ? inbuf[m_iinptr++] : fill_inbuf());
magic[1] = (char)(m_iinptr < m_iinsize ? inbuf[m_iinptr++] : fill_inbuf());
m_imethod = -1; /* unknown yet */
m_ipart_nb++; /* number of parts in gzip file */
m_lheader_bytes = 0;
//m_ilast_member = RECORD_IO;
/* assume multiple members in gzip file except for record oriented I/O */
if (memcmp(magic, GZIP_MAGIC, 2) != 0)
return -2;
m_imethod = (int)get_byte();
if (m_imethod != DEFLATED)
return -1;
//work = unzip;
flags = (uch)get_byte();
if ((flags & ENCRYPTED) != 0)
return -1;
if (flags & CONTINUATION != 0)
return -1;
if (flags & RESERVED != 0)
return -1;
stamp = (ulg)get_byte();
stamp |= ((ulg)get_byte()) << 8;
stamp |= ((ulg)get_byte()) << 16;
stamp |= ((ulg)get_byte()) << 24;
if (stamp != 0 && !m_ino_time) m_ltime_stamp = stamp;
(void)get_byte(); /* Ignore extra flags for the moment */
(void)get_byte(); /* Ignore OS type for the moment */
if ((flags & EXTRA_FIELD) != 0)
{
unsigned len = (unsigned)get_byte();
len |= ((unsigned)get_byte())<<8;
while (len--) (void)get_byte();
}
/* Get original file name if it was truncated */
if ((flags & ORIG_NAME) != 0)
{
char c; /* dummy used for NeXTstep 3.0 cc optimizer bug */
do {c=get_byte();} while (c != 0);
}
/* Discard file comment if any */
if ((flags & COMMENT) != 0)
{
while (get_byte() != 0) /* null */ ;
}
if (m_ipart_nb == 1)
{
m_lheader_bytes = m_iinptr + 2*sizeof(long); /* include crc and size */
}
return 0;
}
int Cunzip::unzip(char *in, int &inlen, char *out)
{
clear_bufs();
m_szinput=in;
m_iinlen=inlen;
m_szoutput=out;
if(get_method()!=0)
return -1;
if (m_imethod == DEFLATED)
{
int res = inflate();
if (res == 3)
{
//error("out of memory");
return -1;
}
else if (res != 0)
{
//error("invalid compressed data--format violated");
return -1;
}
}
//ext_header = 0; /* for next file */
//ext_header = pkzip = 0; /* for next file */
return m_ibytes_out; // add by wzy
}
int Cunzip::inflate()
/* decompress an inflated entry */
{
int e; /* last block flag */
int r; /* result code */
unsigned h; /* maximum struct huft's malloc'ed */
/* initialize window, bit buffer */
wp = 0;
m_ibk = 0;
m_lbb = 0;
/* decompress until the last block */
h = 0;
do {
printf("inlfate no[%d]\n",h++);
m_ihufts = 0;
if ((r = inflate_block(&e)) != 0)
return r;
/*if (m_ihufts > h)
h = m_ihufts;
*/
} while (!e);
/* Undo too much lookahead. The next read will be byte aligned so we
* can discard unused bits in the last meaningful byte.
*/
while (m_ibk >= 8)
{
m_ibk -= 8;
m_iinptr--;
}
/* flush out slide */
flush_output(wp);
/* return success */
#ifdef DEBUG
fprintf(stderr, "<%u> ", h);
#endif /* DEBUG */
return 0;
}
int Cunzip::inflate_block(int *e)
/* last block flag */
/* decompress an inflated block */
{
unsigned t; /* block type */
register ulg b; /* bit buffer */
register unsigned k; /* number of bits in bit buffer */
/* make local bit buffer */
b = m_lbb;
k = m_ibk;
/* read in last block bit */
NEEDBITS(1)
*e = (int)b & 1;
DUMPBITS(1)
/* read in block type */
NEEDBITS(2)
t = (unsigned)b & 3;
DUMPBITS(2)
/* restore the global bit buffer */
m_lbb = b;
m_ibk = k;
/* inflate that block type */
if (t == 2)
return inflate_dynamic();
if (t == 0)
return inflate_stored();
if (t == 1)
return inflate_fixed();
/* bad block type */
return 2;
}
int Cunzip::inflate_stored()
/* "decompress" an inflated type 0 (stored) block. */
{
unsigned n; /* number of bytes in block */
unsigned w; /* current window position */
register ulg b; /* bit buffer */
register unsigned k; /* number of bits in bit buffer */
/* make local copies of globals */
b = m_lbb; /* initialize bit buffer */
k = m_ibk;
w = wp; /* initialize window position */
/* go to byte boundary */
n = k & 7;
DUMPBITS(n);
/* get the length and its complement */
NEEDBITS(16)
n = ((unsigned)b & 0xffff);
DUMPBITS(16)
NEEDBITS(16)
if (n != (unsigned)((~b) & 0xffff))
return 1; /* error in compressed data */
DUMPBITS(16)
/* read and output the compressed data */
while (n--)
{
NEEDBITS(8)
slide[w++] = (uch)b;
if (w == WSIZE)
{
flush_output(w);
w = 0;
}
DUMPBITS(8)
}
/* restore the globals from the locals */
wp = w; /* restore global window pointer */
m_lbb = b; /* restore global bit buffer */
m_ibk = k;
return 0;
}
int Cunzip::inflate_fixed()
/* decompress an inflated type 1 (fixed Huffman codes) block. We should
either replace this with a custom decoder, or at least precompute the
Huffman tables. */
{
int i; /* temporary variable */
struct huft *tl; /* literal/length code table */
struct huft *td; /* distance code table */
int bl; /* lookup bits for tl */
int bd; /* lookup bits for td */
unsigned l[288]; /* length list for huft_build */
/* set up literal table */
for (i = 0; i < 144; i++)
l[i] = 8;
for (; i < 256; i++)
l[i] = 9;
for (; i < 280; i++)
l[i] = 7;
for (; i < 288; i++) /* make a complete, but wrong code set */
l[i] = 8;
bl = 7;
if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0)
return i;
/* set up distance table */
for (i = 0; i < 30; i++) /* make an incomplete code set */
l[i] = 5;
bd = 5;
if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1)
{
huft_free(tl);
return i;
}
/* decompress until an end-of-block code */
if (inflate_codes(tl, td, bl, bd))
return 1;
/* free the decoding tables, return */
huft_free(tl);
huft_free(td);
return 0;
}
int Cunzip::inflate_dynamic()
/* decompress an inflated type 2 (dynamic Huffman codes) block. */
{
int i; /* temporary variables */
unsigned j;
unsigned l; /* last length */
unsigned m; /* mask for bit lengths table */
unsigned n; /* number of lengths to get */
struct huft *tl; /* literal/length code table */
struct huft *td; /* distance code table */
int bl; /* lookup bits for tl */
int bd; /* lookup bits for td */
unsigned nb; /* number of bit length codes */
unsigned nl; /* number of literal/length codes */
unsigned nd; /* number of distance codes */
#ifdef PKZIP_BUG_WORKAROUND
unsigned ll[288+32]; /* literal/length and distance code lengths */
#else
unsigned ll[286+30]; /* literal/length and distance code lengths */
#endif
register ulg b; /* bit buffer */
register unsigned k; /* number of bits in bit buffer */
/* make local bit buffer */
b = m_lbb;
k = m_ibk;
/* read in table lengths */
NEEDBITS(5)
nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */
DUMPBITS(5)
NEEDBITS(5)
nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */
DUMPBITS(5)
NEEDBITS(4)
nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */
DUMPBITS(4)
#ifdef PKZIP_BUG_WORKAROUND
if (nl > 288 || nd > 32)
#else
if (nl > 286 || nd > 30)
#endif
return 1; /* bad lengths */
/* read in bit-length-code lengths */
for (j = 0; j < nb; j++)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -