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

📄 ms-expand.c

📁 LZ77 compression / decompression algorithm
💻 C
字号:
// LZ77 compression / decompression algorithm// this is the compression Microsoft used in Windows *.HLP and *.MRB files// It is also used with Install Shield files.  These files are// recognizable by the letters SZDD in the first 4 bytes.  The file// names for files compressed in this way are usually the name of the// file as it would be installed but with the last character replaced// by '_'// This program is a complete hack.  I am not responsible for the// algorithm code in any way.  I stole the compression code from// somebody else who didn't put a blame line in the file so I've// forgotten who he was.  I just adapted it to run under linux from// the command line.  (D. Risacher)#define MSEXPAND #include <stdio.h>#include <stdlib.h>#define N 4096#define F 16#define THRESHOLD 3#define dad (node+1)#define lson (node+1+N)#define rson (node+1+N+N)#define root (node+1+N+N+N)#define NIL -1#define int16 shortchar *buffer;int16 *node;int16 pos;#include <sys/stat.h>#include <unistd.h>int main (int argc, char**argv){  FILE *fin, *fout;  if (argc != 3) {    fprintf(stderr, "%s: file-to-expand destination\n");    fprintf(stderr, "WARNING: this program is a complete hack.\n");    exit(1);  }  fin = fopen(argv[1],"r");  fout = fopen(argv[2],"w");  expand(fin, fout);  }int16 filelength(int16 f){  struct stat buf;  fstat(f, &buf);  return buf.st_size;}#define min(x,y) (x>y?y:x)int16 insert(int16 i,int16 run){    int16 c,j,k,l,n,match;    int16 *p;    k=l=1;    match=THRESHOLD-1;    p=&root[(unsigned char)buffer[i]];    lson[i]=rson[i]=NIL;    while((j=*p)!=NIL)    {        for(n=min(k,l);n<run&&(c=(buffer[j+n]-buffer[i+n]))==0;n++) ;        if(n>match)        {            match=n;            pos=j;        }        if(c<0)        {            p=&lson[j];            k=n;        }        else if(c>0)        {            p=&rson[j];            l=n;        }        else        {            dad[j]=NIL;            dad[lson[j]]=lson+i-node;            dad[rson[j]]=rson+i-node;            lson[i]=lson[j];            rson[i]=rson[j];            break;        }    }    dad[i]=p-node;    *p=i;    return match;}void delete(int16 z){    int16 j;    if(dad[z]!=NIL)    {        if(rson[z]==NIL)        {            j=lson[z];        }        else if(lson[z]==NIL)        {            j=rson[z];        }        else        {            j=lson[z];            if(rson[j]!=NIL)            {                do                {                    j=rson[j];                }                while(rson[j]!=NIL);                node[dad[j]]=lson[j];                dad[lson[j]]=dad[j];                lson[j]=lson[z];                dad[lson[z]]=lson+j-node;            }            rson[j]=rson[z];            dad[rson[z]]=rson+j-node;        }        dad[j]=dad[z];        node[dad[z]]=j;        dad[z]=NIL;    }}struct header_struct { long magic, magic2; int16 magic3; long filesize; } __attribute__ ((packed));void compress(FILE *f,FILE *out){    int16 ch,i,run,len,match,size,mask;    char buf[17];    buffer=malloc(N+F+(N+1+N+N+256)*sizeof(int16)); // 28.5 k !    if(buffer)    {#ifdef MSEXPAND        struct header_struct header;        header.magic=0x44445A53L; // SZDD        header.magic2=0x3327F088L;        header.magic3=0x0041;        header.filesize=filelength(fileno(f));        fwrite(&header,sizeof(header),1,out);#endif        node=(int16 *)(buffer+N+F);        for(i=0;i<256;i++) root[i]=NIL;        for(i=NIL;i<N;i++) dad[i]=NIL;        size=mask=1;        buf[0]=0;        i=N-F-F;        for(len=0;len<F&&(ch=getc(f))!=-1;len++)        {            buffer[i+F]=ch;            i=(i+1)&(N-1);        }        run=len;        do        {            ch=getc(f);            if(i>=N-F)            {                delete(i+F-N);                buffer[i+F]=buffer[i+F-N]=ch;            }            else            {                delete(i+F);                buffer[i+F]=ch;            }            match=insert(i,run);            if(ch==-1)            {                run--;                len--;            }            if(len++>=run)            {                if(match>=THRESHOLD)                {#ifdef MSEXPAND                    buf[size++]=pos;                    buf[size++]=((pos>>4)&0xF0)+(match-3);#else                    buf[0]|=mask;                    *(int16 *)(buf+size)=((match-3)<<12)|((i-pos-1)&(N-1));                    size+=2;#endif                    len-=match;                }                else                {#ifdef MSEXPAND                    buf[0]|=mask;#endif                    buf[size++]=buffer[i];                    len--;                }                if(!((mask+=mask)&0xFF))                {                    fwrite(buf,size,1,out);                    size=mask=1;                    buf[0]=0;                }            }            i=(i+1)&(N-1);        }        while(len>0);        if(size>1) fwrite(buf,size,1,out);        free(buffer);    }}void expand(FILE *f,FILE *out){    int16 bits,ch,i,j,len,mask;    char *buffer;#ifdef MSEXPAND    struct header_struct header;    i=fread(&header,1,sizeof(header),f);    if(i!=sizeof(header)||header.magic!=0x44445A53L||header.magic2!=0x3327F088L||header.magic3!=0x0041)    {        fwrite(&header,1,i,out);        while((ch=getc(f))!=-1) putc(ch,out);        return;    } #endif    buffer=malloc(N);    if(buffer)    {        i=N-F;        while((bits=getc(f))!=-1)        {            for(mask=0x01;mask&0xFF;mask<<=1)            {#ifdef MSEXPAND                if(!(bits&mask))                {                    j=getc(f);                    if(j==-1) break;                    len=getc(f);                    j+=(len&0xF0)<<4;                    len=(len&15)+3;#else                if(bits&mask)                {                    j=getw(f);                    len=((j>>12)&15)+3;                    j=(i-j-1)&(N-1);#endif                    while(len--)                    {                        putc(buffer[i]=buffer[j],out);                        j=(j+1)&(N-1);                        i=(i+1)&(N-1);                    }                }                else                {                    ch=getc(f);#ifndef MSEXPAND                    if(ch==-1) break;#endif                    putc(buffer[i]=ch,out);                    i=(i+1)&(N-1);                }            }        }        free(buffer);    }}

⌨️ 快捷键说明

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