/* * Read the full COMPRESS-compressed data stream. */ Ics_Error IcsReadCompress (Ics_Header* IcsStruct, void* outbuf, size_t len) { ICSINIT; Ics_BlockRead* br = (Ics_BlockRead*)IcsStruct->BlockRead; unsigned char *stackp; long int code; int finchar; long int oldcode; long int incode; int inbits; int posbits; size_t outpos = 0; size_t insize; int bitmask; long int free_ent; long int maxcode; long int maxmaxcode; int n_bits; size_t rsize; int block_mode; int maxbits; int ii; int offset; unsigned char *inbuf = NULL; unsigned char *htab = NULL; unsigned short *codetab = NULL; /* Dynamically allocate memory that's static in (N)compress. */ inbuf = (unsigned char*)malloc (IBUFSIZ+IBUFXTRA); if (inbuf == NULL) { error = IcsErr_Alloc; goto error_exit; } htab = (unsigned char*)malloc (HSIZE*4); /* Not sure about the size of this thing, original code uses a long int array that's cast to char */ if (htab == NULL) { error = IcsErr_Alloc; goto error_exit; } codetab = (unsigned short*)malloc (HSIZE*sizeof(unsigned short)); if (codetab == NULL) { error = IcsErr_Alloc; goto error_exit; } if ((rsize = fread(inbuf, 1, IBUFSIZ, br->DataFilePtr)) <= 0) { error = IcsErr_FReadIds; goto error_exit; } insize = rsize; if (insize < 3 || inbuf[0] != MAGIC_1 || inbuf[1] != MAGIC_2) { printf("point 1!\n"); error = IcsErr_CorruptedStream; goto error_exit; } maxbits = inbuf[2] & BIT_MASK; block_mode = inbuf[2] & BLOCK_MODE; maxmaxcode = MAXCODE(maxbits); if (maxbits > BITS) { error = IcsErr_DecompressionProblem; goto error_exit; } maxcode = MAXCODE(n_bits = INIT_BITS)-1; bitmask = (1<<n_bits)-1; oldcode = -1; finchar = 0; posbits = 3<<3; free_ent = ((block_mode) ? FIRST : 256); clear_tab_prefixof(); /* As above, initialize the first 256 entries in the table. */ for (code = 255 ; code >= 0 ; --code) { tab_suffixof(code) = (unsigned char)code; } do { resetbuf: offset = posbits >> 3; insize = offset <= insize ? insize - offset : 0; for (ii = 0 ; ii < insize ; ++ii) { inbuf[ii] = inbuf[ii+offset]; } posbits = 0; if (insize < IBUFXTRA) { rsize = fread(inbuf+insize, 1, IBUFSIZ, br->DataFilePtr); if (rsize <= 0 && !feof(br->DataFilePtr)) { error = IcsErr_FReadIds; goto error_exit; } insize += rsize; } inbits = ((rsize > 0) ? (insize - insize%n_bits)<<3 : (insize<<3)-(n_bits-1)); while (inbits > posbits) { if (free_ent > maxcode) { posbits = ((posbits-1) + ((n_bits<<3) - (posbits-1+(n_bits<<3))%(n_bits<<3))); ++n_bits; if (n_bits == maxbits) { maxcode = maxmaxcode; } else { maxcode = MAXCODE(n_bits)-1; } bitmask = (1<<n_bits)-1; goto resetbuf; } input(inbuf,posbits,code,n_bits,bitmask); if (oldcode == -1) { if (code >= 256) { printf("point 3!\n"); error = IcsErr_CorruptedStream; goto error_exit; } ((unsigned char*)outbuf)[outpos++] = (unsigned char)(finchar = (int)(oldcode = code)); continue; } if (code == CLEAR && block_mode) { clear_tab_prefixof(); free_ent = FIRST - 1; posbits = ((posbits-1) + ((n_bits<<3) - (posbits-1+(n_bits<<3))%(n_bits<<3))); maxcode = MAXCODE(n_bits = INIT_BITS)-1; bitmask = (1<<n_bits)-1; goto resetbuf; } incode = code; stackp = de_stack; if (code >= free_ent) { /* Special case for KwKwK string. */ if (code > free_ent) { printf("point 4!\n"); error = IcsErr_CorruptedStream; goto error_exit; } *--stackp = (unsigned char)finchar; code = oldcode; } /* Generate output characters in reverse order */ while (code >= 256) { *--stackp = tab_suffixof(code); code = tab_prefixof(code); } *--stackp = (unsigned char)(finchar = tab_suffixof(code)); /* And put them out in forward order */ ii = de_stack-stackp; if (outpos+ii > len) { ii = len-outpos; /* do not write more in buffer than fits! */ } memcpy(((unsigned char*)outbuf)+outpos, stackp, ii); outpos += ii; if (outpos == len) { goto error_exit; } if ((code = free_ent) < maxmaxcode) { /* Generate the new entry. */ tab_prefixof(code) = (unsigned short)oldcode; tab_suffixof(code) = (unsigned char)finchar; free_ent = code+1; } oldcode = incode; /* Remember previous code. */ } } while (rsize > 0); if (outpos != len) { error = IcsErr_OutputNotFilled; } error_exit: /* Deallocate stuff */ if (inbuf) free(inbuf); if (htab) free(htab); if (codetab) free(codetab); return error; }
int decrunch_compress(xmp_file in, xmp_file out) { char_type *stackp; code_int code; int finchar; code_int oldcode; code_int incode; int inbits; int posbits; int outpos; int insize; int bitmask; code_int free_ent; code_int maxcode; code_int maxmaxcode; int n_bits; int rsize; int maxbits; int block_mode; int i; long bytes_in; /* Total number of byte from input */ long bytes_out; /* Total number of byte to output */ char_type inbuf[IBUFSIZ + 64]; /* Input buffer */ char_type outbuf[OBUFSIZ + 2048];/* Output buffer */ count_int htab[HSIZE]; unsigned short codetab[HSIZE]; bytes_in = 0; bytes_out = 0; insize = 0; rsize = xmp_fread(inbuf, 1, IBUFSIZ, in); insize += rsize; if (insize < 3 || inbuf[0] != MAGIC_1 || inbuf[1] != MAGIC_2) { return -1; } maxbits = inbuf[2] & BIT_MASK; block_mode = inbuf[2] & BLOCK_MODE; maxmaxcode = MAXCODE(maxbits); if (maxbits > BITS) { /*fprintf(stderr, "%s: compressed with %d bits, can only handle %d bits\n", (*ifname != '\0' ? ifname : "stdin"), maxbits, BITS); exit_code = 4; */ return -1; } bytes_in = insize; maxcode = MAXCODE(n_bits = INIT_BITS) - 1; bitmask = (1 << n_bits) - 1; oldcode = -1; finchar = 0; outpos = 0; posbits = 3 << 3; free_ent = ((block_mode) ? FIRST : 256); clear_tab_prefixof(); /* As above, initialize the first 256 entries in the table. */ for (code = 255; code >= 0; --code) tab_suffixof(code) = (char_type) code; do { resetbuf:; { int i; int e; int o; o = posbits >> 3; e = o <= insize ? insize - o : 0; for (i = 0; i < e; ++i) inbuf[i] = inbuf[i + o]; insize = e; posbits = 0; } if (insize < sizeof(inbuf) - IBUFSIZ) { if ((rsize = xmp_fread(inbuf + insize, 1, IBUFSIZ, in)) < 0) return -1; insize += rsize; } inbits = ((rsize > 0) ? (insize - insize % n_bits) << 3 : (insize << 3) - (n_bits - 1)); while (inbits > posbits) { if (free_ent > maxcode) { posbits = ((posbits - 1) + ((n_bits << 3) - (posbits - 1 + (n_bits << 3)) % (n_bits << 3))); ++n_bits; if (n_bits == maxbits) maxcode = maxmaxcode; else maxcode = MAXCODE(n_bits) - 1; bitmask = (1 << n_bits) - 1; goto resetbuf; } input(inbuf, posbits, code, n_bits, bitmask); if (oldcode == -1) { if (code >= 256) { fprintf(stderr, "oldcode:-1 code:%i\n", (int)(code)); fprintf(stderr, "uncompress: corrupt input\n"); /* abort_compress(); */ return -1; } outbuf[outpos++] = (char_type)(finchar = (int)(oldcode = code)); continue; } if (code == CLEAR && block_mode) { clear_tab_prefixof(); free_ent = FIRST - 1; posbits = ((posbits - 1) + ((n_bits << 3) - (posbits - 1 + (n_bits << 3)) % (n_bits << 3))); maxcode = MAXCODE(n_bits = INIT_BITS) - 1; bitmask = (1 << n_bits) - 1; goto resetbuf; } incode = code; stackp = de_stack; if (code >= free_ent) { /* Special case for KwKwK string. */ if (code > free_ent) { /*char_type *p; posbits -= n_bits; p = &inbuf[posbits >> 3]; fprintf(stderr, "insize:%d posbits:%d inbuf:%02X %02X %02X %02X %02X (%d)\n", insize, posbits, p[-1], p[0], p[1], p[2], p[3], (posbits & 07));*/ fprintf(stderr, "uncompress: corrupt input\n"); /* abort_compress(); */ return -1; } *--stackp = (char_type) finchar; code = oldcode; } while ((cmp_code_int) code >= (cmp_code_int) 256) { /* Generate output characters in reverse order */ *--stackp = tab_suffixof(code); code = tab_prefixof(code); } *--stackp = (char_type) (finchar = tab_suffixof(code)); /* And put them out in forward order */ if (outpos + (i = (de_stack - stackp)) >= OBUFSIZ) { do { if (i > OBUFSIZ - outpos) i = OBUFSIZ - outpos; if (i > 0) { memcpy(outbuf + outpos, stackp, i); outpos += i; } if (outpos >= OBUFSIZ) { if (xmp_fwrite(outbuf, 1, outpos, out) != outpos) { return -1; /*write_error(); */ } outpos = 0; } stackp += i; } while ((i = (de_stack - stackp)) > 0); } else { memcpy(outbuf + outpos, stackp, i); outpos += i; } if ((code = free_ent) < maxmaxcode) { /* Generate the new entry. */ tab_prefixof(code) = (unsigned short)oldcode; tab_suffixof(code) = (char_type) finchar; free_ent = code + 1; } oldcode = incode; /* Remember previous code. */ } bytes_in += rsize; } while (rsize > 0); if (outpos > 0 && xmp_fwrite(outbuf, 1, outpos, out) != outpos) return -1; return 0; }