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

📄 lzss.c

📁 一个加密库代码
💻 C
📖 第 1 页 / 共 2 页
字号:

  // no, restore the local variables...
  blDone = pCtx->blSaveDone;
  nI = pCtx->nSaveI;
  nC = pCtx->nSaveC;
  nLen = pCtx->nSaveLen;
  nR = pCtx->nSaveR;
  nS = pCtx->nSaveS;
  nLastMatchLength = pCtx->nSaveLastMatchLength;
  nCodeBufPtr = pCtx->nSaveCodeBufPtr;
  bMask = pCtx->bSaveMask;
  memcpy(code_buf, pCtx->saveCode_buf, 17);
  
  // ...and jump to the last interruption point
  switch (pCtx->wInterruptPoint) {
    case 2 : goto ENTRYPOINT2;
    case 3 : goto ENTRYPOINT3;
  }

  // here we start with the engine setup
ENTRYPOINT1:
  initTree(pCtx);  // initialize trees
  code_buf[0] = 0;  // code_buf[1..16] saves eight units of code, and
                    // code_buf[0] works as eight flags, "1" representing that
                    // the unit is an unencoded letter (1 byte), "0" a position
                    // -and-length pair (2 bytes).  Thus, eight units require at
                    // most 16 bytes of code.
  nCodeBufPtr = bMask =1;
  nS = 0;
  nR = LZSS_N - LZSS_F;
  
  // clear the buffer with any character that might appear often (SPACE)
  for (nI = nS; nI < nR; nI++) pCtx->text_buf[nI] = ' ';
  nLen = 0;
  blDone = BOOL_FALSE;
  
  while (blDone == BOOL_FALSE) 
  {
    // the following entry point will guarantee, that the readByte() call will
    // be repeated when the engine is re-activated, same technique used below
ENTRYPOINT2:
    wTemp = readByte(pCtx);
    // must we interrupt the engine?
    if (wTemp == LZSS_EOB) 
    {
      COMPRESS_SAVE_LOCAL_VAR
      pCtx->wInterruptPoint = 2;
      // return the number of bytes written (will be zero here)
      return pCtx->lBytesWritten;
    }

    // has the stream come to its end?
    if (wTemp == LZSS_EOD) blDone = BOOL_TRUE;
    else 
    {
      // read LZSS_F bytes into the last LZSS_F bytes of the buffer
      pCtx->text_buf[nR + nLen] = (WORD8) wTemp; 
      if (++nLen >= LZSS_F) blDone = BOOL_TRUE;
    }
  }

  // nothing to compress at all?
  if (nLen == 0) return 0;

  // Insert the LZSS_F strings, each of which begins with one or more 'space'
  // characters. Note the order in which these strings are inserted. This way,
  // degenerated trees will be less likely to occur.
  for (nI = 1; nI <= LZSS_F; nI++) insertNode(pCtx, nR - nI); 

  // Finally, insert the whole string just read. The context variables
  // nMatchLength and nMatchPosition are set.
  insertNode(pCtx, nR);

  do 
  {
    // match_length may be spuriously long near the end of text.
    if (pCtx->nMatchLength > nLen) pCtx->nMatchLength = nLen;

    if (pCtx->nMatchLength <= LZSS_THRESHOLD) 
    {
      pCtx->nMatchLength = 1;  // not long enough match, send one byte
      code_buf[0] |= bMask;  // "send one byte" flag
      code_buf[nCodeBufPtr++] = pCtx->text_buf[nR];  // send uncoded
    }
    else 
    {
      code_buf[nCodeBufPtr++] = (WORD8) pCtx->nMatchPosition;

      // send position and length pair, note nMatchLength > LZSS_THRESHOLD.
      code_buf[nCodeBufPtr++] = (WORD8) (((pCtx->nMatchPosition >> 4) & 0xf0) |
                                (pCtx->nMatchLength - (LZSS_THRESHOLD + 1)));
    }
    // shift mask left one bit
    if ((bMask <<= 1) == 0) 
    {
      // send at most 8 units of code together
      for (nI = 0; nI < nCodeBufPtr; nI++) 
        cWriteByte(pCtx, code_buf[nI]);
      code_buf[0] = 0;
      nCodeBufPtr = bMask = 1;
    }
    nLastMatchLength = pCtx->nMatchLength;
    nI = 0;
    blDone = BOOL_FALSE;
    while (blDone == BOOL_FALSE) 
    {
ENTRYPOINT3:
      wTemp = readByte(pCtx);

      // must we interrupt the engine?
      if (wTemp == LZSS_EOB) 
      {
        COMPRESS_SAVE_LOCAL_VAR
        pCtx->wInterruptPoint = 3;

        // return the number of bytes written
        return pCtx->lBytesWritten;
      }
      // has the stream come to its end?
      if (wTemp == LZSS_EOD) 
        blDone = BOOL_TRUE;
      else 
      {
        nC = wTemp;

        // delete old strings and read new bytes
        deleteNode(pCtx, nS);    
        pCtx->text_buf[nS] = (WORD8) nC;

        // if the position is near the end of buffer, extend the buffer to
        // make string comparison easier
        if (nS < (LZSS_F - 1)) pCtx->text_buf[nS + LZSS_N] = (WORD8) nC;

        // since this is a ring buffer, increment the position modulo LZSS_N
        nS = (nS + 1) & (LZSS_N - 1);  
        nR = (nR + 1) & (LZSS_N - 1);  

        // register the string in text_buf[nR..nR + LZSS_F - 1]
        insertNode(pCtx, nR);   
        if (++nI >= nLastMatchLength) blDone = BOOL_TRUE;
      }
    }

    // after the end of text,no need to read, but buffer may not be empty
    while (nI++ < nLastMatchLength) 
    {
      deleteNode(pCtx, nS);                     
      nS = (nS + 1) & (LZSS_N - 1);
      nR = (nR + 1) & (LZSS_N - 1);
      if (--nLen) insertNode(pCtx, nR);
    }
  } 
  while (nLen > 0); // (until all data has been compressed)

  // send remaining code
  if (nCodeBufPtr > 1) 
    for (nI = 0; nI < nCodeBufPtr; nI++) cWriteByte(pCtx, code_buf[nI]);
  
  // remember that lCodeSize just contains the number of all compressed bytes
  return pCtx->lBytesWritten;
}



// macro to save the local variables in a context, used in LZSS_Decompress()
#define DECOMPRESS_SAVE_LOCAL_VAR pCtx->blSaveDone = blDone;    \
                                  pCtx->nSaveI = nI;            \
                                  pCtx->nSaveJ = nJ;            \
                                  pCtx->nSaveK = nK;            \
                                  pCtx->nSaveR = nR;            \
                                  pCtx->nSaveC = nC;            \
                                  pCtx->wSaveFlags = wFlags;




WORD32 CRYPTPAK_API LZSS_Decompress
  (PLZSSCTX pCtx, 
   const void* pSource, 
   void* pTarget, 
   WORD32 lNumOfBytes,
   WORD32 lSizeOfOutputBuffer, 
   WORD8 bCondition, 
   BYTEBOOL* pblRepeatMe) 
{
  BYTEBOOL blDone;
  int nI, nJ, nK, nR, nC;
  WORD16 wFlags;
  WORD16 wTemp; // (this variable mustn't be saved)

  // first set up the i/o pointers and the counters
  pCtx->pDataSource = (WORD8*) pSource;
  pCtx->pDataDrain = (WORD8*) pTarget;
  pCtx->lDrainSize = lSizeOfOutputBuffer;
  pCtx->lSourceSize = lNumOfBytes;
  if (*pblRepeatMe == BOOL_FALSE) pCtx->lBytesRead = 0;
  pCtx->lBytesWritten = 0;

  // end of data stream?
  if ((bCondition & LZSS_STOP) == LZSS_STOP) 
    pCtx->blEOD = BOOL_TRUE;
  else 
    pCtx->blEOD = BOOL_FALSE;

  // must we first launch the compression engine?
  if ((bCondition & LZSS_START) == LZSS_START)    
  {	  
	  blDone = BOOL_FALSE;
	  nJ = nK = nC = 0;
	  goto ENTRYPOINT1;
  }	

  // if not, restore the local variables...
  blDone = pCtx->blSaveDone;
  nI = pCtx->nSaveI;
  nJ = pCtx->nSaveJ;
  nK = pCtx->nSaveK;
  nR = pCtx->nSaveR;
  nC = pCtx->nSaveC;
  wFlags = pCtx->wSaveFlags;

  // ...and jump to the last interrupt point
  switch (pCtx->wInterruptPoint) 
  {
    case 2 : goto ENTRYPOINT2;
    case 3 : goto ENTRYPOINT3;
    case 4 : goto ENTRYPOINT4;
    case 5 : goto ENTRYPOINT5;
    case 6 : goto ENTRYPOINT6;
    case 7 : goto ENTRYPOINT7;
  }

  // here we start with the engine setup
ENTRYPOINT1:
  for (nI = 0; nI < LZSS_N - LZSS_F; nI++) 
    pCtx->text_buf[nI] = ' ';
  nR = LZSS_N - LZSS_F;
  wFlags = 0;
  for (;;)
  {
    if (((wFlags >>= 1) & 256) == 0) 
    {
ENTRYPOINT2:
      wTemp = readByte(pCtx);
      // must we interrupt the engine?
      if (wTemp == LZSS_EOB) 
      {
        DECOMPRESS_SAVE_LOCAL_VAR
        pCtx->wInterruptPoint = 2;
        *pblRepeatMe = BOOL_FALSE;
        return pCtx->lBytesWritten;
      }
      // has the stream come to its end?
      if (wTemp == LZSS_EOD) 
      {
        // yes, everything's finished now
        *pblRepeatMe = BOOL_FALSE;
        return pCtx->lBytesWritten;
      }
      nC = wTemp;
      wFlags = (WORD16) (nC | 0xff00); // uses higher byte cleverly to count 8
    }
    if (wFlags & 1) 
    {
ENTRYPOINT3:
      wTemp = readByte(pCtx);
      // (same input technique as above)
      if (wTemp == LZSS_EOB) 
      {
        DECOMPRESS_SAVE_LOCAL_VAR
        pCtx->wInterruptPoint = 3;
        *pblRepeatMe = BOOL_FALSE;
        return pCtx->lBytesWritten;
      }
      if (wTemp == LZSS_EOD) 
      {
        *pblRepeatMe = BOOL_FALSE;
        return pCtx->lBytesWritten;
      }
      nC = wTemp;
      // can we put out a byte?
ENTRYPOINT4:
      if (dWriteByte(pCtx, (WORD8) nC) == BOOL_FALSE) 
      {
        // no -> set the repeat flag and interrupt the routine
        DECOMPRESS_SAVE_LOCAL_VAR
        pCtx->wInterruptPoint = 4;
        *pblRepeatMe = BOOL_TRUE;
        return pCtx->lBytesWritten;
      }
      pCtx->text_buf[nR++] = (WORD8) nC;
      nR &= (LZSS_N - 1);
    }
    else 
    {
      // (same input techniques as above)
ENTRYPOINT5:
      wTemp = readByte(pCtx);
      if (wTemp == LZSS_EOB) 
      {
        DECOMPRESS_SAVE_LOCAL_VAR
        pCtx->wInterruptPoint = 5;
        *pblRepeatMe = BOOL_FALSE;
        return pCtx->lBytesWritten;
      }
      if (wTemp == LZSS_EOD) 
      {
        *pblRepeatMe = BOOL_FALSE;
        return pCtx->lBytesWritten;
      }
      nI = wTemp;
ENTRYPOINT6:
      wTemp = readByte(pCtx);
      if (wTemp == LZSS_EOB) 
      {
        DECOMPRESS_SAVE_LOCAL_VAR
        pCtx->wInterruptPoint = 6;
        *pblRepeatMe = BOOL_FALSE;
        return pCtx->lBytesWritten;
      } 
      if (wTemp == LZSS_EOD) 
      {
        *pblRepeatMe = BOOL_FALSE;
        return pCtx->lBytesWritten;
      }
      nJ = wTemp;
      nI |= ((nJ & 0xf0) << 4);
      nJ = (nJ & 0x0f) + LZSS_THRESHOLD;
      nK = 0;
      while (nK <= nJ) 
      {
        nC = pCtx->text_buf[(nI + nK) & (LZSS_N - 1)];
ENTRYPOINT7:
        // (same output technique as above)
        if (dWriteByte(pCtx, (WORD8) nC) == BOOL_FALSE) 
        {
          DECOMPRESS_SAVE_LOCAL_VAR
          pCtx->wInterruptPoint = 7;
          *pblRepeatMe = BOOL_TRUE;
          return pCtx->lBytesWritten;
        } 
        pCtx->text_buf[nR++] = (WORD8) nC;
        nR &= (LZSS_N - 1);
        nK++;
      }
    }
  } // of while()
}

⌨️ 快捷键说明

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