| 221 | /* note: inbuf should have at least 1028 bytes beyond buflen */ |
| 222 | |
| 223 | void compress_data(unsigned char *inbuf,int *buflen,unsigned char *outbuf) |
| 224 | { |
| 225 | |
| 226 | #define WINDOW_LEN (1<<17) |
| 227 | #define WINDOW_MASK (WINDOW_LEN-1) |
| 228 | |
| 229 | unsigned char *inrd,*inref,*incmp; |
| 230 | int *rev_similar; /* where is the previous occurrence */ |
| 231 | int **rev_last; /* idem */ |
| 232 | int offs,len,bestoffs,bestlen,lastwrot,i; |
| 233 | int inpos,inlen,outpos; |
| 234 | int *x; |
| 235 | |
| 236 | inlen=*buflen; |
| 237 | inpos=0; |
| 238 | inrd=inbuf; |
| 239 | rev_similar=(int *)malloc(4*WINDOW_LEN); |
| 240 | rev_last=(int **)malloc(256*sizeof(int *)); |
| 241 | if (rev_last) rev_last[0]=(int *)malloc(65536*4); |
| 242 | |
| 243 | if ((outbuf==NULL)||(rev_similar==NULL)|| |
| 244 | (rev_last==NULL)||(rev_last[0]==NULL)) |
| 245 | { printf("Insufficient memory.\n"); abandon_ship(); } |
| 246 | for (i=1;i<256;i++) rev_last[i]=rev_last[i-1]+256; |
| 247 | memset(rev_last[0],0xff,65536*4); |
| 248 | memset(rev_similar,0xff,4*WINDOW_LEN); |
| 249 | |
| 250 | outbuf[0]=0x10; outbuf[1]=0xFB; |
| 251 | outbuf[2]=inlen>>16; outbuf[3]=(inlen>>8)&255; outbuf[4]=inlen&255; |
| 252 | outpos=5; |
| 253 | lastwrot=0; |
| 254 | |
| 255 | /* main encoding loop */ |
| 256 | for (inpos=0,inrd=inbuf;inpos<inlen;inpos++,inrd++) { |
| 257 | if ((inpos&0x3fff)==0) { putchar('.'); fflush(stdout); } |
| 258 | /* adjust occurrence tables */ |
| 259 | x=rev_last[*inrd]+(inrd[1]); |
| 260 | offs=rev_similar[inpos&WINDOW_MASK]=*x; |
| 261 | *x=inpos; |
| 262 | /* if this has already been compressed, skip ahead */ |
| 263 | if (inpos<lastwrot) continue; |
| 264 | |
| 265 | /* else look for a redundancy */ |
| 266 | bestlen=0; i=0; |
| 267 | while ((offs>=0)&&(inpos-offs<WINDOW_LEN)&&(i++<QFS_MAXITER)) { |
| 268 | len=2; incmp=inrd+2; inref=inbuf+offs+2; |
| 269 | while ((*(incmp++)==*(inref++))&&(len<1028)) len++; |
| 270 | if (len>bestlen) { bestlen=len; bestoffs=inpos-offs; } |
| 271 | offs=rev_similar[offs&WINDOW_MASK]; |
| 272 | } |
| 273 | |
| 274 | /* check if redundancy is good enough */ |
| 275 | if (bestlen>inlen-inpos) bestlen=inpos-inlen; |
| 276 | if (bestlen<=2) bestlen=0; |
| 277 | if ((bestlen==3)&&(bestoffs>1024)) bestlen=0; |
| 278 | if ((bestlen==4)&&(bestoffs>16384)) bestlen=0; |
| 279 | |
| 280 | /* update compressed data */ |
no test coverage detected