/* * @(#) lzh.c - LZH compression routine. * (c) 1997 Ivan Maidanski http://ivmai.chat.ru * Freeware program source. All rights reserved. ** * Language: ANSI C * Tested with: Watcom C16 v10.0 * Last modified: 1997-06-09 18:45:00 GMT+04:00 */ #include #include #include #define WINSIZELOG 12 /* >=11 */ #define WINSIZE (1<=TSIZE) { freq[j]=(freq[i]+1)/2; son[j]=son[i]; j++; } for (j=NCHARCNT,i=0;j0;k--) if (fnc) { freq[nc]=freq[k]; freq[k]=f; prnt[i=son[nc]]=k; if (i>=CHAR_BIT-*bitnum; for (*bitnum+=len;*bitnum>=CHAR_BIT;*bitnum-=CHAR_BIT) { putc(*bitbuf,f); *bitbuf=code; code>>=CHAR_BIT; } } unsigned int getcode(FILE *f, unsigned char *bitbuf, unsigned char *bitnum, unsigned char len, short *eofflag) { int c; unsigned int code; for (code=*bitbuf;*bitnum>=len-(*bitnum>CHAR_BIT? *bitnum-CHAR_BIT : 0); *bitnum-=len; } else *bitbuf=*bitnum=0; return (code&((1<>(WINSIZELOG-6)],p_len[pos>>(WINSIZELOG-6)]); putcode(f,bitbuf,bitnum,pos&((1<<(WINSIZELOG-6))-1),WINSIZELOG-6); } unsigned int decodepos(FILE *f, unsigned char *bitbuf, unsigned char *bitnum, short *eofflag) { unsigned char code=getcode(f,bitbuf,bitnum,CHAR_BIT,eofflag); unsigned char len=d_len[code%16]; return (((unsigned int)d_code[code]<<(WINSIZELOG-6)) | (code>>len) | ((unsigned int)getcode(f,bitbuf,bitnum, (WINSIZELOG-6)-(CHAR_BIT-len),eofflag)<<(CHAR_BIT-len))); } void encodeend(FILE *f, unsigned char *bitbuf, unsigned char *bitnum, unsigned short prnt[]) { unsigned short nc; unsigned short k,len; unsigned int code; if (*bitnum) { for (nc=0;ncCHAR_BIT-*bitnum) break; } putcode(f,bitbuf,bitnum,code,CHAR_BIT-*bitnum); } } void compress(FILE *fin, FILE *fout) { int c; unsigned char bitbuf=0,bitnum=0; unsigned int curpos,oldpos,matchpos; unsigned short curlen,matchlen,len; unsigned char textbuf[WINSIZE+LOOKSIZE]; unsigned short freq[TSIZE]; /* 1..MAXFREQ */ unsigned short son[TSIZE]; /* 0..TSIZE+NCHARCNT */ unsigned short prnt[TSIZE+NCHARCNT]; /* 0..TSIZE-1 */ unsigned int subtree[UCHAR_MAX+1]; /* 0..WINSIZE */ unsigned int lson[WINSIZE],rson[WINSIZE],eqson[WINSIZE]; /* 0..WINSIZE */ unsigned int dad[WINSIZE+1]; /* 0..WINSIZE+1 */ huffstart(freq,son,prnt); inittree(subtree,dad); for (oldpos=0;oldpos0;curlen--) insertnode(textbuf,subtree,lson,rson,eqson,dad,curpos-curlen,&matchpos); matchlen=insertnode(textbuf,subtree,lson,rson,eqson,dad,curpos,&matchpos); while (len) { if (matchlen>len) matchlen=len; if (matchlen<=THRESHOLD) { encodenchar(fout,&bitbuf,&bitnum,freq,son,prnt,textbuf[curpos]); matchlen=1; } else { encodenchar(fout,&bitbuf,&bitnum,freq,son,prnt, UCHAR_MAX-THRESHOLD+matchlen); encodepos(fout,&bitbuf,&bitnum,(curpos-matchpos-1)%WINSIZE); } for (curlen=matchlen;curlen>0 && (c=getc(fin))!=EOF; curlen--,oldpos=(oldpos+1)%WINSIZE) { deletenode(subtree,lson,rson,eqson,dad,oldpos,textbuf[oldpos]); textbuf[oldpos]=c; if (oldpos0;curlen--,oldpos=(oldpos+1)%WINSIZE,len--) { deletenode(subtree,lson,rson,eqson,dad,oldpos,textbuf[oldpos]); curpos=(curpos+1)%WINSIZE; matchlen=insertnode(textbuf,subtree,lson,rson,eqson,dad,curpos,&matchpos); } } encodeend(fout,&bitbuf,&bitnum,prnt); } void decompress(FILE *fin, FILE *fout) { unsigned short nc; unsigned char bitbuf=0,bitnum=0; short eofflag; unsigned int curpos,oldpos; unsigned char textbuf[WINSIZE]; unsigned short freq[TSIZE]; /* 1..MAXFREQ */ unsigned short son[TSIZE]; /* 0..TSIZE+NCHARCNT */ unsigned short prnt[TSIZE+NCHARCNT]; /* 0..TSIZE-1 */ huffstart(freq,son,prnt); for (oldpos=0;oldpos "); return (1); } if (!(fin=fopen(argv[2],"rb"))) { puts("Error: cannot open source file!"); return (2); } if (!(fout=fopen(argv[3],"wb"))) { fclose(fin); puts("Error: cannot open target file!"); return (2); } if (argv[1][0]!='D' && argv[1][0]!='d') compress(fin,fout); else decompress(fin,fout); fclose(fin); fclose(fout); return (0); }