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

📄 lzx.c

📁 CHMTools
💻 C
📖 第 1 页 / 共 2 页
字号:
    else {      z = lens[x] - z; if (z < 0) z += 17;      lens[x++] = z;    }  }  lb->bb = bitbuf;  lb->bl = bitsleft;  lb->ip = inpos;  return 0;}int LZXdecompress(UBYTE *inbuf, UBYTE *outbuf, ULONG inlen, ULONG outlen) {  UBYTE *inpos  = inbuf;  UBYTE *outpos  = outbuf;  UBYTE *endinp = inpos + inlen;  UBYTE *window = LZX(window);  UBYTE *runsrc, *rundest;  UWORD *hufftbl; /* used in READ_HUFFSYM macro as chosen decoding table */  ULONG window_posn = LZX(window_posn);  ULONG last_window_posn = 0;  ULONG window_size = LZX(window_size);  ULONG R0 = LZX(R0);  ULONG R1 = LZX(R1);  ULONG R2 = LZX(R2);  register ULONG bitbuf;  register int bitsleft;  ULONG match_offset, i,j,k; /* ijk used in READ_HUFFSYM macro */  struct lzx_bits lb; /* used in READ_LENGTHS macro */  int togo = outlen, this_run, main_element, aligned_bits;  int match_length, length_footer, extra, verbatim_bits;  INIT_BITSTREAM;  /* main decoding loop */  while (togo > 0) {    /* last block finished, new block expected */    if (LZX(block_remaining) == 0) {      if (LZX(block_type) == LZX_BLOCKTYPE_UNCOMPRESSED) {        if (LZX(block_length) & 1) inpos++; /* realign bitstream to word */        INIT_BITSTREAM;      }      /* Moved header read check inside loop and added the code to reset	 the huffman tables and re-read the Intel preprocessing info	 every time a window-size boundary is reached. This is actually not 	 correct, there's a separate parameter for when the tables get reset.	 But all existing CHM files I've seen have that parameter the same	 as the window size.  Consider this a FIXME -- MTR */      if (window_posn == window_size) {	LZX(header_read) = 0;	for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++) LZX(MAINTREE_len)[i] = 0;	for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)   LZX(LENGTH_len)[i]   = 0;	R0 = R1 = R2 = 1;      }            /* read header if necessary */      if (!LZX(header_read)) {	i = j = 0;	READ_BITS(k, 1); if (k) { READ_BITS(i,16); READ_BITS(j,16); }	LZX(intel_filesize) = (i << 16) | j; /* or 0 if not encoded */	LZX(header_read) = 1;      }            READ_BITS(LZX(block_type), 3);      READ_BITS(i, 16);      READ_BITS(j, 8);      LZX(block_remaining) = LZX(block_length) = (i << 8) | j;	  //	fprintf(stderr, "Block type %d at %08x %08x\n", LZX(block_type), inpos - inbuf, outpos - outbuf);      switch (LZX(block_type)) {      case LZX_BLOCKTYPE_ALIGNED:        for (i = 0; i < 8; i++) { READ_BITS(j, 3); LENTABLE(ALIGNED)[i] = j; }        BUILD_TABLE(ALIGNED);        /* rest of aligned header is same as verbatim */      case LZX_BLOCKTYPE_VERBATIM:        READ_LENGTHS(MAINTREE, 0, 256);        READ_LENGTHS(MAINTREE, 256, LZX(main_elements));        BUILD_TABLE(MAINTREE);        if (LENTABLE(MAINTREE)[0xE8] != 0) LZX(intel_started) = 1;        READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS);        BUILD_TABLE(LENGTH);        break;      case LZX_BLOCKTYPE_UNCOMPRESSED:        LZX(intel_started) = 1; /* because we can't assume otherwise */        ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */        if (bitsleft > 16) inpos -= 2; /* and align the bitstream! */        R0=inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;        R1=inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;        R2=inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;        break;      default:        return DECR_ILLEGALDATA;      }    }    /* buffer exhaustion check */    if (inpos > endinp) {      /* it's possible to have a file where the next run is less than       * 16 bits in size. In this case, the READ_HUFFSYM() macro used       * in building the tables will exhaust the buffer, so we should       * allow for this, but not allow those accidentally read bits to       * be used (so we check that there are at least 16 bits       * remaining - in this boundary case they aren't really part of       * the compressed data)       */      if (inpos > (endinp+2) || bitsleft < 16) return DECR_ILLEGALDATA;    }    while ((this_run = LZX(block_remaining)) > 0 && togo > 0) {      //      if (this_run > togo) {      //	fprintf(stderr, "this_run: %08x, togo: %08x\n", this_run, togo);      //      }      if (this_run > togo) this_run = togo;      togo -= this_run;      LZX(block_remaining) -= this_run;      /* apply 2^x-1 mask */      last_window_posn = window_posn;      window_posn &= window_size - 1;      /* runs can't straddle the window wraparound */      if ((window_posn + this_run) > window_size)        return DECR_DATAFORMAT;      switch (LZX(block_type)) {      case LZX_BLOCKTYPE_VERBATIM:        while (this_run > 0) {          READ_HUFFSYM(MAINTREE, main_element);          if (main_element < LZX_NUM_CHARS) {            /* literal: 0 to LZX_NUM_CHARS-1 */            window[window_posn++] = main_element;            this_run--;          }          else {            /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */            main_element -= LZX_NUM_CHARS;              match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;            if (match_length == LZX_NUM_PRIMARY_LENGTHS) {              READ_HUFFSYM(LENGTH, length_footer);              match_length += length_footer;            }            match_length += LZX_MIN_MATCH;              match_offset = main_element >> 3;              if (match_offset > 2) {              /* not repeated offset */              if (match_offset != 3) {                extra = extra_bits[match_offset];                READ_BITS(verbatim_bits, extra);                match_offset = position_base[match_offset] - 2 + verbatim_bits;              }              else {                match_offset = 1;              }                /* update repeated offset LRU queue */              R2 = R1; R1 = R0; R0 = match_offset;            }            else if (match_offset == 0) {              match_offset = R0;            }            else if (match_offset == 1) {              match_offset = R1;              R1 = R0; R0 = match_offset;            }            else /* match_offset == 2 */ {              match_offset = R2;              R2 = R0; R0 = match_offset;            }            rundest = window + window_posn;            runsrc  = rundest - match_offset;            window_posn += match_length;            this_run -= match_length;            /* copy any wrapped around source data */            while ((runsrc < window) && (match_length-- > 0)) {             *rundest++ = *(runsrc + window_size); runsrc++;	     /* -- I think this should never happen -- MTR.  I'm wrong */			 //	     fprintf(stderr, "Assumption violated!\n");            }            /* copy match data - no worries about destination wraps */            while (match_length-- > 0) *rundest++ = *runsrc++;          }	  if ((window_posn % 32768 == 0) && (window_posn != 0)) {	    int b = (bitsleft<16)?bitsleft:(bitsleft-16);	    REMOVE_BITS(b);	    /* -- MTR -- adjust for 32768 block boundaries */	    //	    fprintf(stderr, "32768-block at %08x\n", inpos - inbuf);	  }        }        break;      case LZX_BLOCKTYPE_ALIGNED:        while (this_run > 0) {          READ_HUFFSYM(MAINTREE, main_element);            if (main_element < LZX_NUM_CHARS) {            /* literal: 0 to LZX_NUM_CHARS-1 */            window[window_posn++] = main_element;            this_run--;          }          else {            /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */            main_element -= LZX_NUM_CHARS;              match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;            if (match_length == LZX_NUM_PRIMARY_LENGTHS) {              READ_HUFFSYM(LENGTH, length_footer);              match_length += length_footer;            }            match_length += LZX_MIN_MATCH;              match_offset = main_element >> 3;              if (match_offset > 2) {              /* not repeated offset */              extra = extra_bits[match_offset];              match_offset = position_base[match_offset] - 2;              if (extra > 3) {                /* verbatim and aligned bits */                extra -= 3;                READ_BITS(verbatim_bits, extra);                match_offset += (verbatim_bits << 3);                READ_HUFFSYM(ALIGNED, aligned_bits);                match_offset += aligned_bits;              }              else if (extra == 3) {                /* aligned bits only */                READ_HUFFSYM(ALIGNED, aligned_bits);                match_offset += aligned_bits;              }              else if (extra > 0) { /* extra==1, extra==2 */                /* verbatim bits only */                READ_BITS(verbatim_bits, extra);                match_offset += verbatim_bits;              }              else /* extra == 0 */ {                /* ??? */                match_offset = 1;              }                /* update repeated offset LRU queue */              R2 = R1; R1 = R0; R0 = match_offset;            }            else if (match_offset == 0) {              match_offset = R0;            }            else if (match_offset == 1) {              match_offset = R1;              R1 = R0; R0 = match_offset;            }            else /* match_offset == 2 */ {              match_offset = R2;              R2 = R0; R0 = match_offset;            }            rundest = window + window_posn;            runsrc  = rundest - match_offset;            window_posn += match_length;            this_run -= match_length;            /* copy any wrapped around source data */            while ((runsrc < window) && (match_length-- > 0)) {             *rundest++ = *(runsrc + window_size); runsrc++;            }            /* copy match data - no worries about destination wraps */            while (match_length-- > 0) *rundest++ = *runsrc++;          }	  if ((window_posn % 32768 == 0) && (window_posn != 0)) {	    int b = (bitsleft<16)?bitsleft:(bitsleft-16);	    REMOVE_BITS(b);	    /* -- MTR -- adjust for 32768 block boundaries */	  }        }        break;      case LZX_BLOCKTYPE_UNCOMPRESSED:        if ((inpos + this_run) > endinp) return DECR_ILLEGALDATA;        memcpy(window + window_posn, inpos, this_run);        inpos += this_run; window_posn += this_run;        break;      default:        return DECR_ILLEGALDATA; /* might as well */      }    }    if (window_posn > last_window_posn) {      memcpy(outpos, window + last_window_posn,  window_posn - last_window_posn);      outpos += window_posn - last_window_posn;    }    else {      memcpy(outpos, window + last_window_posn,  window_size - last_window_posn);      outpos += window_size - last_window_posn;      memcpy(outpos, window,  window_posn);      outpos += window_posn;    }  }  if (togo != 0) return DECR_ILLEGALDATA;  LZX(window_posn) = window_posn;  LZX(R0) = R0;  LZX(R1) = R1;  LZX(R2) = R2;  /* intel E8 decoding */  if ((LZX(frames_read)++ < 32768) && LZX(intel_filesize) != 0) {    if (outlen <= 6 || !LZX(intel_started)) {      LZX(intel_curpos) += outlen;    }    else {      UBYTE *data    = outbuf;      UBYTE *dataend = data + outlen - 10;      LONG curpos    = LZX(intel_curpos);      LONG filesize  = LZX(intel_filesize);      LONG abs_off, rel_off;      LZX(intel_curpos) = curpos + outlen;      while (data < dataend) {        if (*data++ != 0xE8) { curpos++; continue; }        abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);        if ((abs_off >= -curpos) && (abs_off < filesize)) {          rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;          data[0] = (UBYTE) rel_off;          data[1] = (UBYTE) (rel_off >> 8);          data[2] = (UBYTE) (rel_off >> 16);          data[3] = (UBYTE) (rel_off >> 24);        }        data += 4;        curpos += 5;      }    }  }  return DECR_OK;}

⌨️ 快捷键说明

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